我可以通过使用很容易地删除数组中的重复项.uniq
,但是如何在不使用该.uniq
方法的情况下执行此操作?
a = [1, 1, 1, 2, 4, 3, 4, 3, 2, 5, 5, 6] class Array def my_uniq self | [] end end a.my_uniq #=> [1, 2, 4, 3, 5, 6]
这使用方法Array#| :"Set Union - 通过将ary与other_ary连接,返回一个新数组,排除任何重复项并保留原始数组中的顺序."
这是各种答案的基准,以及Array#uniq
.
require 'fruity' require 'set' def doit(n, m) arr = n.times.to_a arr = m.times.map { arr.sample } compare do uniq { arr.uniq } Schwern { uniq = []; arr.sort.each { |e| uniq.push(e) if e != uniq[-1]; uniq } } Sharma {b = []; arr.each{ |aa| b << aa unless b.include?(aa) }; b } Mihael { arr.to_set.to_a } sawa { arr.group_by(&:itself).keys } Cary { arr | [] } end end doit(1_000, 500) # Schwern is faster than uniq by 19.999999999999996% ± 10.0% (results differ) # uniq is similar to Cary # Cary is faster than Mihael by 10.000000000000009% ± 10.0% # Mihael is similar to sawa # sawa is faster than Sharma by 5x ± 0.1 doit(100_000, 50_000) # Schwern is faster than uniq by 50.0% ± 10.0% (results differ) # uniq is similar to Cary # Cary is similar to Mihael # Mihael is faster than sawa by 10.000000000000009% ± 10.0% # sawa is faster than Sharma by 310x ± 10.0
"Schwern"和"uniq"返回包含相同元素但不以相同顺序排列的数组(因此"结果不同").
这是@Schern要求的额外基准.
def doit1(n) arr = n.times.map { rand(n/10) } compare do uniq { arr.uniq } Schwern { uniq = []; arr.sort.each { |e| uniq.push(e) if e != uniq[-1]; uniq } } Sharma {b = []; arr.each{ |aa| b << aa unless b.include?(aa) }; b } Mihael { arr.to_set.to_a } sawa { arr.group_by(&:itself).keys } Cary { arr | [] } end end doit1(1_000) # Cary is similar to uniq # uniq is faster than sawa by 3x ± 1.0 # sawa is similar to Schwern (results differ) # Schwern is similar to Mihael (results differ) # Mihael is faster than Sharma by 2x ± 0.1 doit1(50_000) # Cary is similar to uniq # uniq is faster than Schwern by 2x ± 1.0 (results differ) # Schwern is similar to Mihael (results differ) # Mihael is similar to sawa # sawa is faster than Sharma by 62x ± 10.0