通过从另外两个“Bool”数组中随机选择值来创建一个“Bool”数组

Create a `Bool` array by randomly selecting values from two other `Bool` arrays

这里有两个数组true/false

a = [true, true, false, true, false]
b = [true, false, false, false, true]

我愿意创建一个新数组 c,其中 c 的每个元素来自 a 或来自 b 的概率相等

以下是我找到的两个解决方案:

c=trues(5)
for i = 1:5
  c[i] = rand() > 0.5 ? a[i] : b[i]
end

c=trues(5)
ab = hcat(a,b)
which = sample([1,2], 5)
for i = 1:5
  c[i] = ab[i,which[i]]
end

是否有更好(更快)的解决方案?

我会这样说:

r = randbit(5)
c = [ r[i] ? a[i] : b[i] for i = 1:5 ]

第一行有效地生成了一个随机布尔值数组 r(实际上是一个位数组,但这是一个实现细节)。第二行根据 r 中的值从 ab 中选择元素,使用 array comprehension,这相当于你的 for 循环但稍微多一点清晰可辨。

这与 jch 的回答略有不同,但使用位操作可能比理解 select ab 的元素更快=56=] r:

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

请注意,我已经更正了这个问题的位操作答案

这个问题我原来的回答是说selecta或者b根据掩码r的方法是a&r|b。然而,由于这个公式缺乏对称性而烦恼,我更仔细地研究了这个问题,生成了一个完整的事实 table 并将公式更正为 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

原来的公式对于真值table中的8个条目之一是错误的,当mask是true但是afalse,ortrue b 错误地导致 true。解决方法是使用 a 和掩码,掩码与 b 的补码,或结果。这是真相table:

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

现在进行一些分析

我的直觉是这个问题的位操作解决方案比使用 ? 运算符的理解要快得多。对这些操作进行计时表明,对于大型数组,位操作速度快了几个数量级,内存占用也少得多。这是我在 abr 的长度为 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)

因此,如果您使用的是小型数组,这两种技术都可以,但位操作对于非常大的数组更有效。