如果你想把代码放在一个方法中,你必须考虑到 Ruby 通过值而不是通过引用来传递参数。为什么在第一种情况下这似乎有效,我不知道,这本身可能是一个问题。所以我用 ! 结束了第一个方法的名称。 (到位)但不是其他两个。
我用三种不同的方法做了一些基准测试,包括?解决方案显然获胜。放置数组的初始值需要时间,但所有解决方案都必须这样做,因此您可以丢弃它。
require 'set'
require 'benchmark'
def add_item1!(item, list)
list << item unless list.include?(item)
end
def add_item2(item, list)
list |= [item]
end
def add_item3(item, list)
set = Set.new(list)
set << item
list = set.to_a
end
array1 = [3,2,1,4]
add_item1!(2, array1) # [3, 2, 1, 4]
add_item1!(5, array1) # [3, 2, 1, 4, 5]
array2 = [3,2,1,4]
array2 = add_item2(2, array2) # [3, 2, 1, 4]
array2 = add_item2(5, array2) # [3, 2, 1, 4, 5]
array3 = [3,2,1,4]
array3 = add_item3(2, array3) # [3, 2, 1, 4]
array3 = add_item3(5, array3) # [3, 2, 1, 4, 5]
TESTS = 100000
Benchmark.bmbm do |results|
results.report("unless not new") {TESTS.times {array1 = [3,2,1,4];add_item1!(2, array1) }}
results.report("unless new") {TESTS.times{array1 = [3,2,1,4];add_item1!(5, array1) }}
results.report("|= not new") {TESTS.times{array2 = [3,2,1,4];array2 = add_item2(2, array2) }}
results.report("|= new") {TESTS.times{array2 = [3,2,1,4];array2 = add_item2(5, array2) }}
results.report("Set not new") {TESTS.times{array3 = [3,2,1,4];array3 = add_item3(2, array3) }}
results.report("Set new") {TESTS.times{array3 = [3,2,1,4];array3 = add_item3(5, array3) }}
end
# user system total real
# unless not new 0.031000 0.000000 0.031000 ( 0.027002)
# unless new 0.047000 0.000000 0.047000 ( 0.052003)
# |= not new 0.125000 0.000000 0.125000 ( 0.118007)
# |= new 0.125000 0.000000 0.125000 ( 0.126007)
# Set not new 0.358000 0.000000 0.358000 ( 0.354020)
# Set new 0.359000 0.000000 0.359000 ( 0.364021)