14

我正在和 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我会得到ERROR: syntax: missing separator in array expression. 如果我包装x, y一些东西,我总是会得到那种输出—— Array、、Array{Any}Tuple

我的猜测:有些东西我只是不明白。有人愿意帮助我理解什么吗?

4

7 回答 7

12

我认为理解不适合您尝试做的事情。原因可以在Julia 手册的数组理解部分找到:

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

这种形式的含义是 F(x,y,...) 是用变量 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 单元格中的内容。返回的元组不会自动扩展为数组的行。

如果您想从理解中获得一个 5x2 数组,您需要确保x长度为 5 且长度为 2。然后每个单元格将包含使用来自和y的每个可能的元素对评估的函数的结果作为论据。问题是示例数组的单元格中的值实际上并不需要评估两个参数的函数。相反,您要做的只是将两个预定的列粘在一起形成一个二维数组。为此,使用或文字:xyhcat

  • 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) )
于 2013-10-13T20:16:07.300 回答
11

我认为您只是错误地阅读了列表理解

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),或者更好的是只使用两个数组(一个用于 int,一个用于 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)
于 2013-10-13T19:42:30.340 回答
1

我有点喜欢@fawr 在保持可变性的同时为数据类型的效率提供的答案,但这很快就能满足您的要求(根据肖恩的回答):

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 类型的方法。

于 2014-04-20T03:10:15.423 回答
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
于 2014-07-03T22:23:52.730 回答
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[:])
于 2014-02-10T11:59:28.037 回答
0

正如@ivarne 所说

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

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

于 2014-04-01T17:42:00.257 回答
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...)

其中A将是 a 9x2 Array{Int64,2},其中true/false1/表示0

我已经在 J​​ulia 0.4.7 中测试了这些。

于 2017-12-21T15:33:26.210 回答