Julia中的多维数组理解

时间:2013-10-13 17:00:09

标签: julia

我正在和Julia讨厌,似乎无法使多维数组理解起作用。我正在为OSX使用0.20-pre的夜间版本;这可能是构建中的一个错误。但我怀疑,这是用户的一个错误。

让我们说我想结束这样的事情:

5x2 Array
1 6
2 7
3 8
4 9
5 10

我不想只打电话给reshape。据我所知,应该生成一个多维数组,如:[(x, y) for x in 1:5, y in 6:10]。但是这会生成一个5x5的元组数组:

julia> [(x, y) for x in 1:5, y in 6:10]
5x5 Array{(Int64,Int64),2}:
 (1,6)  (1,7)  (1,8)  (1,9)  (1,10)
 (2,6)  (2,7)  (2,8)  (2,9)  (2,10)
 (3,6)  (3,7)  (3,8)  (3,9)  (3,10)
 (4,6)  (4,7)  (4,8)  (4,9)  (4,10)
 (5,6)  (5,7)  (5,8)  (5,9)  (5,10)

或者,也许我想为每个生成一组值和一个布尔代码:

5x2 Array
1 false
2 false
3 false
4 false
5 false

同样,我似乎只能用{(x, y) for x in 1:5, y=false}创建一个元组数组。如果我删除x, y周围的parens,我会ERROR: syntax: missing separator in array expression。如果我将x, y包裹在某个内容中,我总会获得相应的输出 - ArrayArray{Any}Tuple

我的猜测:有些东西我没有到达这里。有谁愿意帮我理解什么?

7 个答案:

答案 0 :(得分:8)

我认为你只是阅读列表理解错误

julia> [x+5y for  x in 1:5, y in 0:1]
5x2 Array{Int64,2}:
 1   6
 2   7
 3   8
 4   9
 5  10

当您在多个维度中使用它们时,您将获得两个变量,并且需要基于坐标的单元格值函数

对于你的第二个问题,我认为你应该重新考虑你的要求。 Julia使用类型化数组来实现性能,并且可以在不同列中存储不同类型。要获得一个无类型的数组,你可以使用{}而不是[],但我认为更好的解决方案是拥有一个元组数组(Int,Bool),甚至更好的只使用两个数组(一个用于整数,一个用于bool )。

julia> [(i,false) for i in 1:5]
5-element Array{(Int64,Bool),1}:
 (1,false)
 (2,false)
 (3,false)
 (4,false)
 (5,false)

答案 1 :(得分:7)

我认为理解不适合你想要做的事情。原因可以在Array Comprehension section of the Julia Manual

中找到
A = [ F(x,y,...) for x=rx, y=ry, ... ]
  

这种形式的含义是用变量x,y等计算F(x,y,...),取其给定值列表中的每个值。值可以指定为任何可迭代对象,但通常是1:n或2:(n-1)之类的范围,或者像[1.2,3.4,5.7]这样的显式数组。 结果是Nd密集数组,其维度是变量范围rx,ry等的维度的串联,并且每个F(x,y,...)评估返回标量。

这里需要注意的是,如果将其中一个变量设置为> 1维数组,则它似乎首先变平;所以“结果是......一个维度是变量范围rx,ry等维度的串联”的声明并不准确,因为如果rx是2x2且ry是3,那么你不会得到2x2x3的结果,而是4x3。但是你得到的结果应该是有道理的:你正在返回一个元组,这就是Array单元格中的内容。返回的元组没有自动扩展到数组的行中。

如果你想从comprhension获得一个5x2数组,你需要确保x的长度为5,y的长度为2.然后每个单元格将包含使用xy中每个可能的元素配对作为参数评估函数的结果。问题在于,示例数组的单元格中的值实际上并不需要评估两个参数的函数。相反,你要做的只是将两个预定的列粘在一起成为一个2D数组。为此,请使用hcat或文字:

  • hcat(1:5, 6:10)
  • [ 1:5 5:10 ]
  • hcat(1:5, falses(5))
  • [ 1:5 falses(5) ]

如果你想创建一个2D数组,其中第2列包含在第1列评估的函数的结果,你可以这样理解:

f(x) = x + 5
[ y ? f(x) : x for x=1:5, y=(false,true) ]

但是这有点令人困惑,而且对我来说似乎更直观

x = 1:5
hcat( x, map(f,x) )

答案 2 :(得分:1)

你的直觉是写[(x, y) for x in 1:5, y in 6:10],但你需要的是将范围包装在zip中,如下所示:

[i for i in zip(1:5, 6:10)]

它为您提供了非常接近您需要的东西,即:

5-element Array{(Int64,Int64),1}:
(1,6) 
(2,7) 
(3,8) 
(4,9) 
(5,10)

要获得您正在寻找的内容,您需要:

hcat([[i...] for i in zip(1:5, 6:10)]...)'

这会给你:

5x2 Array{Int64,2}:
1   6
2   7
3   8
4   9
5  10

答案 3 :(得分:0)

这是另一种方式(虽然令人费解):

x1 = 1
x2 = 5

y1 = 6
y2 = 10

x = [x for x in x1:x2, y in y1:y2]
y = [y for x in x1:x2, y in y1:y2]

xy = cat(2,x[:],y[:])

答案 4 :(得分:0)

@ivarne指出

[{x,false} for  x in 1:5]

会起作用并给你一些可变的东西

答案 5 :(得分:0)

我有点像@fawr在保留可变性的同时为数据类型的效率所给出的答案,但这很快就能得到你所要求的(使用Shawn的答案):

hcat(1:5,6:10)
hcat({i for i=1:5},falses(5))

第二部分中的单元格数组理解强制数据类型为Any而不是IntXX

这也有效:

hcat(1:5,{i for i in falses(5)})

除了理解之外,我还没有找到另一种方法来显式地将数组转换为Any类型。

答案 6 :(得分:0)

我找到了一种通过vcatsplat运算符生成数值多维数组的方法:

R = [ [x y] for x in 1:3, y in 4:6 ] # make the list of rows
A = vcat(R...) # make n-dim. array from the row list

然后R将是3x3 Array{Array{Int64,2},2}A9x2 Array{Int64,2},如您所愿。

对于第二种情况(一组值和每个的布尔代码),可以执行类似

的操作
R = [[x y > 5] for x in 1:3, y in 4:6] # condition is y > 5
A = vcat(R...)

其中A9x2 Array{Int64,2},其中true / false1 / 0表示。

我在朱莉娅0.4.7测试了那些。