Ruby中的“哈希的哈希”习语是什么?

34

在Ruby中创建哈希的哈希允许方便地进行二维(或更高维)查找。然而,插入时必须始终检查第一个索引是否已经存在于哈希表中。例如:

h = Hash.new
h['x'] = Hash.new if not h.key?('x')
h['x']['y'] = value_to_insert

最好采取以下方式并自动创建新的哈希:

h = Hash.new
h['x']['y'] = value_to_insert

同样地,当查找一个第一索引并不存在的值时,最好返回nil而不是收到'[]'未定义方法的错误。

looked_up_value = h['w']['z']

可以创建一个哈希包装类来实现这种行为,但是是否存在一种现有的 Ruby 习惯用语来完成这个任务?


有没有哈希的哈希习惯用语,在特定深度后返回0?(我正在计算东西,我正在使用h[:foo][:bar][:baz] += 1) - Andrew Grimm
2个回答

54
你可以传递一个块给Hash.new函数,该块会在需要返回默认值时执行:
h = Hash.new { |h, k| h[k] = Hash.new }

当然,这可以通过递归实现。有一篇文章解释了详细信息
为了完整起见,这里是该文章给出的任意深度哈希的解决方案:
hash = Hash.new(&(p = lambda{|h, k| h[k] = Hash.new(&p)}))

最初提出这个解决方案的人是Kent Sibilev


链接失效了。不过解决方案很出色。 - Dean Radcliffe
1
这里切换了死链接:http://inquirylabs.com/blog2009/2006/09/20/ruby-hashes-of-arbitrary-depth/。 - millisami
3
那个链接现在也失效了 :-( - Adam Spiers
1
这是一个指向Internet Archive Wayback Machine的链接。至少它应该会保留一段时间! https://web.archive.org/web/20090331170758/http://blog.inquirylabs.com/2006/09/20/ruby-hashes-of-arbitrary-depth/ - Br.Bill
1
@Br.Bill 确实,谢谢,我已经编辑了。像这样的小修正,您可以随意自行进行编辑。 - Konrad Rudolph

4

所谓的自动化嵌套数据结构,即 autovivification,是一把双刃剑。问题在于,如果你在定义一个值之前“查看”它,那么你就会得到一个空哈希表,以后需要剪枝。

如果您不介意有些混乱,您可以始终使用或等于风格的声明,以允许您在查询时构建预期的结构:

((h ||= { })['w'] ||= { })['z']

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接