不进行迭代似乎是一个很好的目标,但是正确地执行迭代将会非常快。
基准测试很重要:
require 'benchmark'
DATA = ['a','b','c','a','b','c','a','b','c']
INDEXES = [2,5,8]
def ttm(data)
d2 = data.dup
INDEXES.sort.reverse.each{ |i| d2.delete_at(i) }
d2
end
def devon_parsons(data)
new_data = data.each_with_index.reject do |value,index|
INDEXES.include? index
end.map(&:first)
new_data
end
def arup_rakshit(data)
data.values_at(*(0...data.size).to_a - INDEXES)
end
def sawa(data)
data.values_at(*data.each_index.to_a - INDEXES)
end
确保进行比较的是同等条件下的测试:
ttm(DATA)
devon_parsons(DATA)
arup_rakshit(DATA)
sawa(DATA)
运行基准测试:
n = 100_000
Benchmark.bm(13) do |b|
b.report('ttm:') { n.times { ttm(DATA) } }
b.report('devon_parsons') { n.times { devon_parsons(DATA) } }
b.report('arup_rakshit') { n.times { arup_rakshit(DATA) } }
b.report('sawa') { n.times { sawa(DATA) } }
end
这导致:
如果数据量增加:
DATA2 = DATA * 100
Benchmark.bm(13) do |b|
b.report('ttm:') { n.times { ttm(DATA2) } }
b.report('devon_parsons') { n.times { devon_parsons(DATA2) } }
b.report('arup_rakshit') { n.times { arup_rakshit(DATA2) } }
b.report('sawa') { n.times { sawa(DATA2) } }
end
结果真的变了:
当数组大小发生变化时,测试其运行情况非常重要。在小数组上运行良好的代码可能会随着数组增长而变得明显缓慢。而且,往往看起来很酷的做法实际上因为存在隐藏成本而非常慢。基准测试可以帮助我们找出这些问题。
注意:使用 sort.reverse
非常重要。如果没有这些内容,数组将被破坏。
可以进一步改进 sort 方法,使用 sort_by(&:itself)
require 'benchmark'
array = (0..99).to_a.shuffle
n = 100_000
Benchmark.bm(7) do |b|
b.report('sort:') { n.times { array.sort } }
b.report('sort_by:') { n.times { array.sort_by(&:itself) } }
end
导致:
user system total real
sort: 0.460000 0.010000 0.470000 ( 0.480236)
sort_by: 3.600000 0.030000 3.630000 ( 3.627871)
增加数组大小:
array = (0..999).to_a.shuffle
Benchmark.bm(13) do |b|
b.report('sort:') { n.times { array.sort } }
b.report('sort_by:') { n.times { array.sort_by(&:itself) } }
end
导致:
user system total real
sort: 9.520000 0.120000 9.640000 ( 9.659246)
sort_by: 53.530000 0.720000 54.250000 ( 54.321285)
c
只是巧合吗? - Anthonydelete_at(i)
更改为delete_at(* i)
? - Cary Swoveland