反转阵列的最佳方式?

时间:2011-06-17 19:46:18

标签: ruby

如果我有像

这样的数组
ary = [0, 0, 3, 0, 0, 0, 2, 0, 1, 0, 1, 1, 0] 

获取阵列中有多少索引的列表的最佳性能是什么?

inverted = [2,2,2,6,6,8,10,11] 

这就是我想出来的,但似乎有一种更有效的方式:

a = []
ary.each_with_index{|v,i| a << Array.new(v, i) if v != 0}
a.flatten
 => [2, 2, 2, 6, 6, 8, 10, 11] 

2 个答案:

答案 0 :(得分:5)

除非分析证明这是一个瓶颈,否则清洁工是一种功能性方法:

>> ary.each_with_index.map { |x, idx| [idx]*x }.flatten(1)
=> [2, 2, 2, 6, 6, 8, 10, 11]

如果您使用Ruby 1.9,我建议这样做(感谢sawa指出Enumerable#flat_map):

>> ary.flat_map.with_index { |x, idx| [idx]*x }
=> [2, 2, 2, 6, 6, 8, 10, 11]

[编辑:使用injecteach_with_object移除了示例,它们不太可能比flat_map + with_index更快

答案 1 :(得分:1)

您可以使用Array#push而不是Array#&lt;&lt;加快这一点。

ary.each_with_index{|v,i| a.push(*Array.new(v, i)) if v != 0}

一些快速基准测试表明,这比使用<<快了约30%。

> ary = [0, 0, 3, 0, 0, 0, 2, 0, 1, 0, 1, 1, 0] 
# => [0, 0, 3, 0, 0, 0, 2, 0, 1, 0, 1, 1, 0]
> quick_bench(10**5) do
> a = []
> ary.each_with_index{|v,i| a << Array.new(v, i) if v != 0}
> a.flatten
> end
Rehearsal ------------------------------------
   1.200000   0.020000   1.220000 (  1.209861)
--------------------------- total: 1.220000sec

       user     system      total        real
   1.150000   0.000000   1.150000 (  1.147103)
# => nil
> quick_bench(10**5) do
> a = []
> ary.each_with_index{|v,i| a.push(*Array.new(v, i)) if v != 0}
> end
Rehearsal ------------------------------------
   0.870000   0.000000   0.870000 (  0.865190)
--------------------------- total: 0.870000sec

       user     system      total        real
   0.860000   0.000000   0.860000 (  0.858628)
# => nil
> a = []
# => []
> ary.each_with_index{|v,i| a.push(*Array.new(v, i)) if v != 0}
# => [0, 0, 3, 0, 0, 0, 2, 0, 1, 0, 1, 1, 0]
> a
# => [2, 2, 2, 6, 6, 8, 10, 11]
> 
相关问题