我是Julia的新手,来自Matlab和Python。
我不了解用于向量数组的条件赋值的Julia语法。在我看来,这似乎与条件分配数字数组不一致。
对于数字数组,我可以执行以下操作:
a = [1,2,3]
b = [0,1,1]
a[b.>0] .= 5
这将a的两个元素替换为新值5。
我的实际工作示例是一个数组,其元素类型为Array {Int64,1}:
a = [[1,0,0], [0,1,0], [0,0,1]]
b = [0,1,1]
a[b.>0] .= Int64[0,0,5]
这不起作用,输出为: 错误:DimensionMismatch(“无法广播数组以匹配目标位置”)
但是,此行有效:
a[b.>0] .= [Int64[0,0,5]]
我无法理解这一点,因为在后一种情况下,按元素分配(。=)对我而言意义不大,因为左右两个数组的大小不同。
有人可以解释吗?
谢谢。
答案 0 :(得分:3)
逻辑索引仅选择条件为真的那些元素。对于a[b.>0]
,选择两个元素:
julia> a[b.>0]
2-element Array{Int64,1}:
2
3
您试图将三个元素分配到这两个位置:
julia> a[b.>0] .= [10,20,30]
ERROR: DimensionMismatch("array could not be broadcast to match destination")
您可以做的是也使用相同的条件逻辑对要分配的值数组进行子集化,以选择应分配的两个元素:
julia> a[b.>0] .= [10,20,30][b.>0]
2-element view(::Array{Int64,1}, [2, 3]) with eltype Int64:
20
30
julia> a
3-element Array{Int64,1}:
1
20
30
语法a[b.>0] .= [Int64[0,0,5]]
仅在a
是Any
数组的情况下才有效,这意味着完全不同。它将值数组本身广播到所有选定的位置-也就是说,它将整个数组作为重复元素放入a
!
julia> a = Any[1,2,3]
3-element Array{Any,1}:
1
2
3
julia> a[b.>0] .= [Int64[0,0,5]]
2-element view(::Array{Any,1}, [2, 3]) with eltype Any:
[0, 0, 5]
[0, 0, 5]
julia> a
3-element Array{Any,1}:
1
[0, 0, 5]
[0, 0, 5]
答案 1 :(得分:3)
操作:
x .= y
尝试遍历x
和y
并执行分配。一个简单的例子是:
julia> x = [1,2,3,4]
4-element Array{Int64,1}:
1
2
3
4
julia> y = [12,14]
2-element Array{Int64,1}:
12
14
julia> x[[2,4]] .= y
2-element view(::Array{Int64,1}, [2, 4]) with eltype Int64:
12
14
julia> x
4-element Array{Int64,1}:
1
12
3
14
我们看到左侧和右侧有2个元素,因此可以执行就地分配。
然后Julia有了一个特殊的规则,即如果右侧容器的长度为1,则可以将其扩展以匹配左侧的尺寸(这也适用于大于1的尺寸,但让我们着眼于简单情况)。
例如,您拥有:
julia> x = [1,2,3,4]
4-element Array{Int64,1}:
1
2
3
4
julia> x[[2,4]] .= 11
2-element view(::Array{Int64,1}, [2, 4]) with eltype Int64:
11
11
julia> x
4-element Array{Int64,1}:
1
11
3
11
julia> length(11)
1
julia> x[[2,4]] .= [11]
2-element view(::Array{Int64,1}, [2, 4]) with eltype Int64:
11
11
julia> x
4-element Array{Int64,1}:
1
11
3
11
julia> length([1])
1
这里要注意的关键一点是,[1]
和1
在这种情况下的行为完全相同,因为在广播中,数字被视为拥有该数字的1元素容器。
现在来看您的示例:
a = [[1,0,0], [0,1,0], [0,0,1]]
b = [0,1,1]
a[b.>0] .= Int64[0,0,5]
失败,因为:
julia> length(a[b.>0])
2
julia> length(Int64[0,0,5])
3
我们发现尺寸不匹配。
但是在:
a[b.>0] .= [Int64[0,0,5]]
您有:
julia> length([Int64[0,0,5]])
1
因此,一个长度为1的容器会扩展。
但是请注意,很可能您不想执行a[b.>0] .= [Int64[0,0,5]]
分配,因为a
将拥有相同的数组Int64[0,0,5]
。例如
julia> a = [[1,0,0], [0,1,0], [0,0,1]]
3-element Array{Array{Int64,1},1}:
[1, 0, 0]
[0, 1, 0]
[0, 0, 1]
julia> b = [0,1,1]
3-element Array{Int64,1}:
0
1
1
julia> a[b.>0] .= [Int64[0,0,5]]
2-element view(::Array{Array{Int64,1},1}, [2, 3]) with eltype Array{Int64,1}:
[0, 0, 5]
[0, 0, 5]
julia> a
3-element Array{Array{Int64,1},1}:
[1, 0, 0]
[0, 0, 5]
[0, 0, 5]
julia> a[2][1] = 100
100
julia> a
3-element Array{Array{Int64,1},1}:
[1, 0, 0]
[100, 0, 5]
[100, 0, 5]
,在大多数情况下,这不是您想要的。例如,像这样的for
循环是一种更安全的方法:
julia> a = [[1,0,0], [0,1,0], [0,0,1]]
3-element Array{Array{Int64,1},1}:
[1, 0, 0]
[0, 1, 0]
[0, 0, 1]
julia> b = [0,1,1]
3-element Array{Int64,1}:
0
1
1
julia> for i in axes(b, 1)
b[i] > 0 && (a[i] = Int64[0,0,5])
end
julia> a
3-element Array{Array{Int64,1},1}:
[1, 0, 0]
[0, 0, 5]
[0, 0, 5]
julia> a[2][1] = 100
100
julia> a
3-element Array{Array{Int64,1},1}:
[1, 0, 0]
[100, 0, 5]
[0, 0, 5]
您会看到a
的每个条目都是一个不同的对象。