【发布时间】:2010-09-29 11:09:45
【问题描述】:
我有一个数组,我想做一个散列,这样我就可以快速询问“X 在数组中吗?”。
在 perl 中,有一种简单(快速)的方法:
my @array = qw( 1 2 3 );
my %hash;
@hash{@array} = undef;
这会生成一个如下所示的哈希:
{
1 => undef,
2 => undef,
3 => undef,
}
我在 Ruby 中想出的最好的方法是:
array = [1, 2, 3]
hash = Hash[array.map {|x| [x, nil]}]
给出:
{1=>nil, 2=>nil, 3=>nil}
有没有更好的 Ruby 方法?
编辑 1
不,Array.include?这不是一个好主意。它的慢。它在 O(n) 而不是 O(1) 中进行查询。为简洁起见,我的示例数组包含三个元素;假设实际有一百万个元素。让我们做一些基准测试:
#!/usr/bin/ruby -w
require 'benchmark'
array = (1..1_000_000).to_a
hash = Hash[array.map {|x| [x, nil]}]
Benchmark.bm(15) do |x|
x.report("Array.include?") { 1000.times { array.include?(500_000) } }
x.report("Hash.include?") { 1000.times { hash.include?(500_000) } }
end
生产:
user system total real
Array.include? 46.190000 0.160000 46.350000 ( 46.593477)
Hash.include? 0.000000 0.000000 0.000000 ( 0.000523)
【问题讨论】:
-
不要忘记考虑转换所需的时间。当然,如果您的情况允许,使用一组开头(如@Zach Langley 建议的那样)可以避免此成本。
-
公平地说,上面的基准应该包括从数组转换为哈希
-
@drhenner 在理论上,当然。在实践中,不是真的——它基本上是无关紧要的。转换完成一次,查找很多很多次。当我问这个问题时,我忘记了我在做什么,但在实际程序中,在转换一次之后,查找可能已经完成了数百万次。