使用具有默认值的哈希

Fab*_*res 3 ruby hash default new-operator

我正在学习用 ruby​​ 编码。我正在学习哈希,但我不理解此代码:count = Hash.new(0). 它说 0 是默认值,但是当我在 irb 上运行它时,它给了我一个空哈希 {}。如果 0 是默认值,为什么我看不到类似count ={0=>0}. 或者零是一个累加器但不去键或值?谢谢

小智 7

如果您尝试访问不存在的散列中的键,则 0 将是后备

例如:

count = Hash.new -> count['key'] => nil

对比

count = Hash.new(0) -> count['key'] => 0

  • @melcher Hash 默认有两个常见的问题:(1) 不小心与`Hash.new([])` 之类的东西共享了引用,所以`h = Hash.new([]); h[:v].push(11)` 有副作用;(2) 没有使用 `Hash.new(some_value)` 自动激活,所以 `h = Hash.new(0); puts h[:v]` 给你 `0` 但不添加 `:v` 作为键,但如果你从 `h = Hash.new { |h, k| 开始,它会 h[k] = 0 }`。虽然不确定是哪个意思。 (2认同)

小智 6

扩展@jeremy-ramos 的答案和@mu-is-too-short 的评论。

以这种方式默认哈希值有两个常见的问题。

1. 不小心共享的参考文献。

Ruby 使用内存中与您传入的完全相同的对象作为每个丢失键的默认值。

对于不可变对象(如0),没有问题。但是您可能想要编写如下代码:

hash = Hash.new([])
hash[key] << value
Run Code Online (Sandbox Code Playgroud)

或者

hash = Hash.new({})
hash[key][second_key] = value
Run Code Online (Sandbox Code Playgroud)

这不会达到您的预期。它不会hash[unknown_key]返回新的空数组或哈希,而是为每个键返回完全相同的数组/哈希对象。

这样做:

hash = Hash.new([])
hash[key1] << value1
hash[key2] << value2
Run Code Online (Sandbox Code Playgroud)

结果是一个散列,其中key1key2都指向包含以下内容的同一数组对象[value1, value2]

请参阅此处相关问题

解决方案

为了解决这个问题,您可以创建一个带有默认块参数的散列(每当访问丢失的键时就会调用它,并让您为丢失的键分配一个值)

hash = Hash.new{|h, key| h[key] = [] }
Run Code Online (Sandbox Code Playgroud)

2. 为遗漏的按键分配默认值

当您访问返回默认值的丢失键时,您可能期望散列现在将包含该键以及返回的值。它不是。Ruby 不会修改哈希值,它只是返回默认值。因此,例如:

hash = Hash.new{|h, key| h[key] = [] }
Run Code Online (Sandbox Code Playgroud)

解决方案

这种混乱也可以使用块方法来解决,其中可以显式设置它们的键值。

  • 这正是我在@jeremyramos 的回答下发表评论的地方。OP 中的问题非常有洞察力(无论是否有意),我认为它值得足够的关注。 (2认同)