我最喜欢@MarkThomas 的回答,但为了速度和内存效率,我建议:
flatter = {}.tap{ |h| original.values.each{ |h2| h.merge!(h2) } }
对当前答案的 200,000 次迭代进行基准测试表明这是最快的:
user system total real
Phrogz 0.710000 0.020000 0.730000 ( 0.728706)
Joshua Creek 0.830000 0.010000 0.840000 ( 0.830700)
Mark Thomas symbol 1.460000 0.020000 1.480000 ( 1.486463)
Mark Thomas to_proc 1.540000 0.030000 1.570000 ( 1.565354)
Tim Peters 1.650000 0.030000 1.680000 ( 1.678283)
由于@tokland 的评论——<code>original.values.reduce(:update)——修改了原始哈希,我们无法直接将其与其他方法进行比较。但是,如果我们修改所有测试以将第一个哈希的副本放回原始每次迭代中,@tokland 的答案将变得最快,尽管仍然不如我的快:
user system total real
tokland's destroyer 0.760000 0.010000 0.770000 ( 0.772774)
Phrogz 1.020000 0.020000 1.040000 ( 1.034755)
Joshua Creek 1.060000 0.000000 1.060000 ( 1.063874)
Mark Thomas symbol 1.780000 0.040000 1.820000 ( 1.816909)
Mark Thomas to_proc 1.790000 0.030000 1.820000 ( 1.819014)
Tim Peters 1.800000 0.040000 1.840000 ( 1.827984)
如果您需要绝对速度并且可以修改原始值,请使用@tokland 的答案。如果您这样做并希望完好无损地保留原始未合并的哈希,那么您可以:
first_k,orig_v = original.each{ |k,v| break [k,v.dup] }
merged = original.values.reduce(:update)
original[first_k] = orig_v
请注意,您的问题标题是traverse;如果你真的不想合并这些值——如果你可能想访问重复键两次而不是最后一次获胜——那么只需执行以下操作:
original.values.each{ |h| h.each{ |k,v|
# hey, we're traversing inside!
} }