1

我想在其键和列表上加入哈希
示例:

a={"aa"=>[1, 2], "bbb"=>[3, 4, 5], "c"=>[6, 7, 8], "hh"=>[9]}
b=["aa","c"]

(b 列表的元素将始终存在于哈希中)

我想加入一个带有散列的列表并保留散列的值。所以我需要得到以下信息:

c={"aa"=>[1,2],"c"=>[6,7,8]}

最快的方法是什么?我的哈希可以包含多达 110.000 个键。
提前致谢

4

6 回答 6

3
c = b.reduce({}) { |memo,x| memo[x]=a[x]; memo }
# => {"aa"=>[1, 2], "c"=>[6, 7, 8]} 

[编辑]只是为了好玩,这里是一些策略的基准:“减少”、“每个”和“设置”:

require 'benchmark'
require 'set'
a = {"aa"=>[1, 2], "bbb"=>[3, 4, 5], "c"=>[6, 7, 8], "hh"=>[9]} 
b = ["aa", "c"]
n = 1_000
Benchmark.bm(8) do |x|
  x.report("reduce:") { n.times { b.reduce({}) { |memo,x| memo[x]=a[x]; memo } } }
  x.report("each:") { n.times { c={}; b.each{|key| c[key] = a[key]} } }
  x.report("set:") { n.times { bset=Set.new ['aa','c']; a.select{|k,v| bset.include? k} } }
end

看起来“每个”对于这个愚蠢的基准测试来说是最有效的:

               user     system      total        real
reduce:    0.000000   0.000000   0.000000 (  0.003384)
each:      0.010000   0.000000   0.010000 (  0.002549) # <-- winner!
set:       0.010000   0.000000   0.010000 (  0.012549)
于 2013-05-24T14:44:36.097 回答
3

遍历数组:

a={"aa"=>[1, 2], "bbb"=>[3, 4, 5], "c"=>[6, 7, 8], "hh"=>[9]}
b=["aa","c"]
c = {}
b.each{|key| c[key] = a[key]}
#=>{"aa"=>[1, 2], "c"=>[6, 7, 8]}
于 2013-05-24T14:44:48.657 回答
2
a = {"aa"=>[1, 2], "bbb"=>[3, 4, 5], "c"=>[6, 7, 8], "hh"=>[9]} 
b = ["aa", "c"] 
a.select{|k,v| b.include? k}
#=> {"aa"=>[1, 2], "c"=>[6, 7, 8]} 

您应该考虑使用一个集合,因为它在语义上是正确的,并且比从Array#include?.

require 'set'
a = {"aa"=>[1, 2], "bbb"=>[3, 4, 5], "c"=>[6, 7, 8], "hh"=>[9]} 
b = Set.new ["aa", "c"] 
a.select{|k,v| b.include? k}
#=> {"aa"=>[1, 2], "c"=>[6, 7, 8]} 
于 2013-05-24T14:31:05.893 回答
2
a={"aa"=>[1, 2], "bbb"=>[3, 4, 5], "c"=>[6, 7, 8], "hh"=>[9]}
b=["aa","c"]
h = b.each_with_object({}) { |i, h| h[i] = a[i] }
p h
# => {"aa"=>[1, 2], "c"=>[6, 7, 8]}

另一种选择:

Hash[b.zip(a.values_at(*b))]
# => {"aa"=>[1, 2], "c"=>[6, 7, 8]}
于 2013-05-24T14:47:17.707 回答
2

基准!

require 'benchmark'
require 'set'
a = {}
("aaaa".."gggg").each{|k| a[k]=true}
p a.size #=>109675
b = a.keys.sample(1000) #try other numbers

b_set=b.to_set
c={}

Benchmark.bm(15) do |x|
  x.report("select"){a.select{|k,v| b.include? k}}
  x.report("set"){a.select{|k,v| b_set.include? k}}
  x.report("array.each"){b.each{|key| c[key] = a[key]}}
  x.report("array.inject"){b.reduce({}) { |memo,x| memo[x]=a[x]; memo }}
  x.report("assoc"){Hash[b.map{|i| a.assoc(i)}]}
  x.report("values_at"){Hash[b.zip(a.values_at(*b))]}
end

输出(在一台古老的笔记本电脑上):

                      user     system      total        real
select           22.860000   0.030000  22.890000 ( 24.454489)
set               0.100000   0.000000   0.100000 (  0.115898)
array.each        0.000000   0.000000   0.000000 (  0.001589)
array.inject      0.000000   0.000000   0.000000 (  0.001265)
assoc            26.090000   0.060000  26.150000 ( 29.330769)
values_at         0.000000   0.000000   0.000000 (  0.001455)
于 2013-05-24T15:18:55.320 回答
1
b=["aa","c"]
a={"aa"=>[1, 2], "bbb"=>[3, 4, 5], "c"=>[6, 7, 8], "hh"=>[9]}
Hash[b.map{|i| a.assoc(i)}]
#=> {"aa"=>[1, 2], "c"=>[6, 7, 8]}
于 2013-05-24T14:55:27.073 回答