如何在Julia中将多维数组解包为变量

4
在Python中,我可以做到以下几点:
a = array([[1,2],[3,4]])
row1, row2 = a

在Julia中有没有等效的一行代码?这个似乎不起作用:
a = [[1 2]; [3 4]]
row1, row2 = a

不过它将row1设置为1,row2设置为3。谢谢!
4个回答

3

根据您的需求,您可以使用Vector{Vector{T}}(类似于Python的列表嵌套)代替MatrixArray{T,2})。这取决于您要做什么。

v0.5+版本中,只需使用[ , ]即可实现:

julia> VERSION
v"0.5.0-dev+4440"

julia> a = [[1, 2], [3, 4]]
2-element Array{Array{Int64,1},1}:
 [1, 2]
 [3, 4]

julia> a = [[1, 2]; [3, 4]]
4-element Array{Int64,1}:
 1
 2
 3
 4

julia> row1, row2 = a;

julia> (row1, row2)
(2-element Array{Int64,1}:
 1
 2,2-element Array{Int64,1}:
 3
 4)

v0.4+版本中,您需要将数组作为数组的数组输入,就像这样:
julia> VERSION
v"0.4.5"

julia> a = Vector[[1, 2], [3, 4]]
2-element Array{Array{T,1},1}:
 [1,2]
 [3,4]

julia> b = [[1, 2]; [3, 4]]
4-element Array{Int64,1}:
 1
 2
 3
 4

julia> c = [[1, 2], [3, 4]]
WARNING: [a,b] concatenation is deprecated; use [a;b] instead
 in depwarn at deprecated.jl:73
 in oldstyle_vcat_warning at abstractarray.jl:29
 in vect at abstractarray.jl:32
while loading no file, in expression starting on line 0
4-element Array{Int64,1}:
 1
 2
 3
 4

julia> row1, row2 = a;

julia> row1, row2
([1,2],[3,4])

有趣,谢谢。尽管迄今为止所有的答案都有有用的见解,但只有你的答案让我能够实际执行row1, row2 = a,所以我将接受这个答案。 - marius
2
再次强调,这个答案并没有提供一个精确的等价物,因为Julia代码复制,而Python代码返回视图。 - Jiahao Chen
2
@JiahaoChen,执行row1, row2 = a并不会复制任何东西,据我所知:julia> a = [[1, 2], [3, 4]]; row1, row2 = a; row1[1] = 7; @assert a[1] == [7, 2]>>> a = [[1, 2], [3, 4]]; row1, row2 = a; row1[0] = 7; assert a[0] == [7, 2],实际上是同一个数组/列表(相同的id/对象),我更担心性能问题,但有时候人们确实想要数组的数组而不是矩阵作为数据结构,这完全取决于具体情况。 - HarmonicaMuse
我的错误。我不知道为什么我说了那句话。 - Jiahao Chen

3
我能想到的Julia语言中最短的一行代码是:
r1, r2 = [sub(a, i, :) for i=1:2]

它不如手写效率高。
r1 = sub(a, 1, :)
r2 = sub(a, 2, :)

因为第一个版本创建了一个临时数组,然后将其拆分到左侧的元组中。
注意:
NumPy的新版本(1.10或更高版本)现在返回数组的视图,而不是副本。在Julia 0.4中,通过"sub"创建视图,通过切片创建副本。因此,在Julia中。
r1 = a[1,:]

这句话的意思是,“不等同于类似的NumPy / Python语句”。
r1 = a[0,:]

视图和副本的主要区别是,如果r1是视图,则更改a的条目将更改r1的条目,但如果r1是副本,则不会更改其条目。副本的缺点是它们占用更多的内存空间。

1
sub已被view替换了吗? - Alan
row1, row2 = view.(Ref(a), [1,2], :) - Friedrich -- Слава Україні

2
在Julia中,数组比2-D矩阵更加通用。因此,“行”这个概念不太清晰,程序员可能有更多的选项来切割数组。因此,需要在表达式中加入更多信息。
我想到的版本是:
row1, row2 = ([vec(a[i,:]) for i in 1:size(a,1)]...)

解释:

  • ([ ]...) 将向量转换为元组
  • size(a,2) 返回行数
  • vec( ) 将数组转换为向量,因为索引矩阵是一个矩阵。
  • [ <...> for i in <...>] 是一个数组推导式(Python 也有)
  • row1, row2 = <...tuple...> 解包元组并将值分配给变量。

像 Julia 和 Python 这样的通用语言都是图灵完备的,所以可以做任何事情,但不必期望代码太相似。Julia 的方式希望是更好的方式。


1
谢谢。更加简洁的写法是:row1, row2 = [a[i,:][:] for i in 1:size(a,1)] - marius
说实话,我有点惊讶,似乎没有像Python那样更易于阅读的版本...虽然我并没有完全看到意思上的问题,但Numpy也具有N-D数组,当将其拆分成一组变量时,其意思是清晰明确的。 - marius
请注意,在Julia 0.4中,a[1,:]与Python/NumPy中的a[0,:] 等价,对于较新版本的NumPy(v1.9+),前者返回一个副本,而后者返回一个视图。 - Jiahao Chen

1
julia 1.1 提供了 eachrow
a = [[1 2]; [3 4]]
row1, row2 = eachrow(a)

row1, row2                 # ([1, 2], [3, 4])

还有eachcol

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接