使用true / false值数组选择数组元素的最佳方法是什么?

时间:2015-12-10 20:49:33

标签: arrays ruby

我有两个数组:

a = [1, 2, 3, 4]
b = [true, true, false, false]

选择ab中相应元素为true的{​​{1}}元素的最佳方式是什么?在这个例子中,我希望:

result = [1, 2]

我这样做:

zipped = a.zip(b)
zipped.select{ |z| z[1] }.map{ |n| n.first }
# => [1, 2]

我想知道纯Ruby中的最佳解决方案,但我也愿意接受GSL等的建议。

性能

array_size = 4000
iterations = 1000

Benchmark.bm do |bm|
  bm.report do
    iterations.times do
      a.each_with_index.map { |a, i| a if b[i] }.compact
    end
  end
end

Benchmark.bm do |bm|
  bm.report do
    iterations.times do
      zipped = a.zip(b).select{ |z| z[1] }.map{ |n| n.first }
    end
  end
end

以下性能表明map each_with_index不仅更具可读性,而且在大型数组上也更快。

     user     system      total        real
   0.610000   0.000000   0.610000 (  0.608642)
       user     system      total        real
   0.880000   0.000000   0.880000 (  0.882018)

5 个答案:

答案 0 :(得分:11)

将布尔值变为枚举器 - 没有zip,也没有数组查找。

a = [1,2,3,4]
b = [true, true, false, false].to_enum

a.select{b.next}  # => [1, 2]

答案 1 :(得分:6)

我觉得这很清晰,并且清楚地表达了语义。

a.select.with_index {|_, i| b[i] }

事实证明,@steenslag以更优雅的方式击败了我4分钟:-D

答案 2 :(得分:2)

如果你正在寻找更短的东西

a.each_with_index.map { |a, i| a if b[i] }.compact会做,但它既不快也不可读。你必须定义最好的方法。

答案 3 :(得分:1)

如果您的目标只是简洁,并且您已经定义了a,b和结果数组,那么我的第一直觉就是:

b.each_with_index { |val,i| results.push( a[i] ) if val }

现在,这样更好吗?不一定,不......但是你可以在任何人能够最终说出来之前阐述你的定义。

答案 4 :(得分:1)

ans = []
b.each_with_index do |boolean, idx|
  ans << a[idx] if boolean
end
ans