Julia 向量数组的条件赋值语法
我是Julia的新手,更多来自Matlab和Python 我无法理解向量数组条件赋值的Julia语法。在我看来,它似乎与数字数组的条件赋值不一致 对于数字数组,我可以执行以下操作:Julia 向量数组的条件赋值语法,julia,Julia,我是Julia的新手,更多来自Matlab和Python 我无法理解向量数组条件赋值的Julia语法。在我看来,它似乎与数字数组的条件赋值不一致 对于数字数组,我可以执行以下操作: a = [1,2,3] b = [0,1,1] a[b.>0] .= 5 这将用新值5替换a的两个元素 我的实际工作示例是使用数组{Int64,1}类型元素的数组: a = [[1,0,0], [0,1,0], [0,0,1]] b = [0,1,1] a[b.>0] .= Int64[0,0,5]
a = [1,2,3]
b = [0,1,1]
a[b.>0] .= 5
这将用新值5替换a的两个元素
我的实际工作示例是使用数组{Int64,1}类型元素的数组:
a = [[1,0,0], [0,1,0], [0,0,1]]
b = [0,1,1]
a[b.>0] .= Int64[0,0,5]
这不起作用,输出为:
错误:维度不匹配(“无法广播数组以匹配目标”)
但是,这条线可以工作:
a[b.>0] .= [Int64[0,0,5]]
我无法理解这一点,因为在后一种情况下,元素赋值(.=)对我来说就更没有意义了,因为左侧和右侧的两个数组具有不同的大小
有人能解释一下吗
提前感谢。逻辑索引仅选择条件为真的元素。对于
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]
行动:
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
在这种情况下的行为完全相同,因为数字被视为一个在广播中包含该数字的单元素容器
现在来看您的示例:
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]
在大多数情况下,这不是你想要的。一种更安全的方法是,例如,像这样为循环创建一个:
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
的每个条目都是一个不同的对象。这是一个非常好的答案(我同时写了我的,然后注意到了你的:)。我有一个小注释a
不必有任何类型,它的类型允许向量{Int64}
元素就足够了。是的,非常正确。我过度简化了那里的文本,Any
数组最有可能同时包含Int
和Vector{Int}
,因为这是它们唯一常见的超类型,但是联合
当然也可以做到这一点。