Ruby中的数组和哈希性能

我有一个程序可以存储一个类的许多实例,比方说高达10.000或更多。 类实例有几个我不时需要的属性,但最重要的是ID。

class Document attr_accessor :id def ==(document) document.id == self.id end end 

现在,存储数千个这些对象的最快方法是什么?

我曾经把它们全部放入一个文档数组中:

 documents = Array.new documents << Document.new # etc 

现在可以select将其存储在Hash中:

 documents = Hash.new doc = Document.new documents[doc.id] = doc # etc 

在我的应用程序中,我主要需要了解一个文档是否存在。 哈希的has_key? 函数显着快于数组的线性search和Document对象的比较? 都在O(n)之内还是has_key? 甚至O(1) 。 我会看到不同之处吗?

另外,有时我需要添加文件,当它已经存在。 当我使用一个数组,我将不得不与include?检查include? 之前,当我使用哈希,我只是使用has_key? 再次。 同上面的问题。

你怎么看? 当90%的时间我只需要知道ID是否存在(而不是对象本身!)时,什么是存储大量数据的最快方法?

哈希值查找快得多:

 require 'benchmark' Document = Struct.new(:id,:a,:b,:c) documents_a = [] documents_h = {} 1.upto(10_000) do |n| d = Document.new(n) documents_a << d documents_h[d.id] = d end searchlist = Array.new(1000){ rand(10_000)+1 } Benchmark.bm(10) do |x| x.report('array'){searchlist.each{|el| documents_a.any?{|d| d.id == el}} } x.report('hash'){searchlist.each{|el| documents_h.has_key?(el)} } end # user system total real #array 2.240000 0.020000 2.260000 ( 2.370452) #hash 0.000000 0.000000 0.000000 ( 0.000695) 

Ruby在标准库中有一个set类,你有没有考虑只保留一个(额外的)一组ID?

http://stdlib.rubyonrails.org/libdoc/set/rdoc/index.html

引用文档:“这是Array的直观互操作设施和Hash快速查找的混合体”。

  1. 使用一组文件。 它有你想要的大多数属性(恒定时间查找,不允许重复)。 Smalltalkers会告诉你,使用已经有你想要的属性的集合是最重要的战斗。

  2. 通过文档ID使用哈希值的文档,|| =用于条件插入(而不是has_key?)。

哈希是专为常量插入和查找而devise的。 Ruby的Set在内部使用Hash。

请注意您的Document对象将需要实现#hash和#eql? 正确的做法是让它们按照你所期望的那样作为哈希键或集合的成员,因为它们被用来定义哈希相等。

使用唯一值时,可以使用前面提到的Ruby Set 。 这里是基准testing结果。 它比哈希稍慢。

  user system total real array 0.460000 0.000000 0.460000 ( 0.460666) hash 0.000000 0.000000 0.000000 ( 0.000219) set 0.000000 0.000000 0.000000 ( 0.000273) 

我只是添加到@ steenslag的代码,可以在这里findhttps://gist.github.com/rsiddle/a87df54191b6b9dfe7c9 。

我用ruby 2.1.1p76进行这个testing。