制作uniq阵列的最快方法是什么?

时间:2015-10-22 08:52:10

标签: arrays ruby unique

我有以下情况。我有一大堆随机字符串。该数组应尽可能快地独特。

现在通过一些基准测试,我发现ruby的uniq很慢:

require 'digest'
require 'benchmark'

#make a nice random array of strings
list = (1..100000).to_a.map(&:to_s).map {|e| Digest::SHA256.hexdigest(e)}
list += list
list.shuffle

def hash_uniq(a)
  a_hash = {}
  a.each do |v|
    a_hash[v] = nil
  end
  a_hash.keys
end

Benchmark.bm do |x|
  x.report(:uniq) { 100.times { list.uniq} }
  x.report(:hash_uniq) { 100.times { hash_uniq(list) } }
end

要点 - > https://gist.github.com/stillhart/20aa9a1b2eeb0cff4cf5

结果非常有趣。可能是红宝石的uniq很慢吗?

          user     system      total        real
uniq      23.750000   0.040000  23.790000 ( 23.823770)
hash_uniq 18.560000   0.020000  18.580000 ( 18.591803)

现在我的问题:

  1. 有没有更快的方法让数组独一无二?

  2. 我做错了吗?

  3. Array.uniq方法有什么问题吗?

  4. 我正在使用ruby 2.2.3p173(2015-08-18修订版51636)[x86_64-linux]

1 个答案:

答案 0 :(得分:3)

对大型数据集的字符串解析操作肯定不是Ruby所发挥的作用。如果这对业务至关重要,您可能希望在C或Go之类的内容中编写扩展,或者让其他应用程序在将其传递给Ruby应用程序之前处理它。

那就是说。您的基准测试似乎有些奇怪。使用Ruby 2.2.3在我的MacBook Pro上运行相同的操作会产生以下结果:

          user        system    total     real
uniq      10.300000   0.110000  10.410000 ( 10.412513)
hash_uniq 11.660000   0.210000  11.870000 ( 11.901917)

建议uniq稍快一些。

如果可能,您应该始终尝试使用正确的集合类型。如果您的收藏品真的与众不同,请使用Set。它们具有更好的内存配置文件,Hash的查找速度更快,同时保留了一些Array直觉。

但是,如果您的数据已经在Array,那么这可能不是一个很好的权衡,因为插入Set的速度相当慢,正如您在此处所见:

              user        system    total     real
uniq          11.040000   0.060000  11.100000 ( 11.102644)
hash_uniq     12.070000   0.230000  12.300000 ( 12.319356)
set_insertion 12.090000   0.200000  12.290000 ( 12.294562)

我添加了以下基准:

x.report(:set_insertion) { 100.times { Set.new(list) } }