操作:
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 的每个条目都是一个不同的对象。