这与 jch 的答案略有不同,但使用位操作而不是根据“掩码”r 选择 a 和 b 的元素可能会更快:
julia> r = bitrand(5)
5-element BitArray{1}:
true
true
false
false
false
julia> r&a | ~r&b
5-element BitArray{1}:
true
true
false
false
true
请注意,我已更正此问题的位操作答案
在我对这个问题的原始回答中,我说过根据掩码r 选择a 或b 的方式是a&r|b。然而被这个公式缺乏对称性所困扰,我更仔细地研究了这个问题,生成了一个完整的真值表并将公式更正为r&a | ~r&b:
julia> r = [trues(4), falses(4)]
julia> a = [trues(2), falses(2)]
julia> a = [a, a]
julia> b = [true, false]
julia> b = [b, b, b, b]
julia> c = r&a | ~r&b
julia> nocigar = a&r|b
julia> q = [r[i] ? a[i] : b[i] for i in 1:length(a)]
julia> all([c[i] == q[i] for i in 1:length(a)])
true
julia> all([nocigar[i] == q[i] for i in 1:length(a)])
false
当掩码为true 但a 为false,or 与true b 错误地导致@ 时,原始公式对于真值表中的 8 个条目之一出错987654337@。解决方法是用a 和掩码,用b 补码掩码,或者得到结果。这是真值表:
julia> hcat(a, b, r, c, nocigar)
8x5 Array{Bool,2}:
true true true true true
true false true true true
false true true false true
false false true false false
true true false true true
true false false false false
false true false true true
false false false false false
现在进行一些分析
我的直觉是,这个问题的位操作解决方案比使用 ? 运算符的理解要快得多。对这些操作进行计时表明,对于大型数组,位操作速度要快几个数量级,并且内存密集度要少得多。这是a、b 和r 的长度为 10^6 时得到的结果:
julia> a = bitrand(10^6)
...
julia> @time c = r&a | ~r&b
elapsed time: 0.000607186 seconds (500496 bytes allocated)
julia> @time c = [r[i] ? a[i] : b[i] for i in 1:length(a)]
elapsed time: 0.446756657 seconds (167967416 bytes allocated, 16.91% gc time)
多次运行这些分配会产生一致的结果。对于较短的数组,长度为 100,执行时间几乎没有差异,但理解使用更多内存:
julia> a = bitrand(100)
...
julia> @time c = r&a | ~r&b
elapsed time: 1.3979e-5 seconds (464 bytes allocated)
julia> @time c = [r[i] ? a[i] : b[i] for i in 1:length(a)]
elapsed time: 5.326e-5 seconds (10520 bytes allocated)
因此,如果您使用的是小型数组,任何一种技术都可以,但位操作对于非常大的数组更有效。