2012-07-28 145 views
0

检查Ruby哈希对象的所有键是否指向空数组的最快方法是什么?快速Ruby哈希访问

我目前的做法:

h = {"a" => [1,2,3], "b" => []} 
var = "something" if h.values.flatten.size > 0 

另一种方法:

h = {"a" => [1,2,3], "b" => []} 
var = "something" if h.values.flatten.empty? 

任何其他demonstrably更快的方法?

+0

也许只是重写“setter”方法,以便在设置时间内跟踪此属性是否已被违反? – rogerdpack 2013-01-17 00:23:50

回答

4

平展会导致您的代码重新分配一个新的,更大的缓冲区。你可以跳过扁平化这样的:

h.values.all? &:empty? 

基准:

Benchmark.measure {100000.times{ h.values.all? &:empty? }} 
# => 0.100000 0.000000 0.100000 ( 0.096073) 

Benchmark.measure {100000.times{ h.values.flatten.empty? }} 
# => 0.140000 0.000000 0.140000 ( 0.143457) 

更大的标杆,包括h.all? {|_,v| v.empty?}

h = {} 
(1...10000).each {|i| h[i] = []} # Pathological case 

Benchmark.measure {1000.times{ h.values.flatten.empty? }} 
# => 1.880000 0.000000 1.880000 ( 1.882853) 
Benchmark.measure {1000.times{ h.values.all? &:empty? }} 
# => 1.750000 0.000000 1.750000 ( 1.748415) 
Benchmark.measure {1000.times{ h.all? {|_,v| v.empty?} }} 
# => 4.140000 0.000000 4.140000 ( 4.137548) 
+1

你根本不需要'h.values':'h.all? {| _,v | v.empty? }' – 2012-07-28 05:50:16

+1

Symbol#to_proc似乎比一个块稍快,但不是太多: 'irb(main):017:0> Benchmark.measure {100000.times {h.all? {| _,V | v.empty?}}} => 0.090000 0.000000 0.090000(0.097628)' – 2012-07-28 05:52:45

+0

我得到的结果相反。也许你应该使用更大的'h'。 – 2012-07-28 05:53:42

1

让我们贪婪:

all_empty = true 

h.each_value do |value| 
    unless value.empty? 
    all_empty = false 
    break 
    end 
end 

基准:

h = {} 
(1...10000).each {|i| h[i] = []} 

Benchmark.measure {1000.times{ h.values.flatten.empty? }} 
=> 2.020000 0.000000 2.020000 ( 2.026274) 
Benchmark.measure {1000.times{ h.values.all? &:empty? }} 
=> 1.750000 0.000000 1.750000 ( 1.750908) 
Benchmark.measure {1000.times{ h.all? {|_,v| v.empty?} }} 
=> 3.570000 0.000000 3.570000 ( 3.570945) 
Benchmark.measure {1000.times{ <code above> }} # Worst case 
=> 1.530000 0.000000 1.530000 ( 1.529857) 
+0

@rogerdpack:当然,它以某种方式迷路了。 :d – InternetSeriousBusiness 2013-01-19 09:24:16