8

Ruby 允许您定义散列的默认值:

h=Hash.new(['alright'])
h['meh'] # => ["alright"]

显示哈希时会显示值的分配,但修改后的默认值不会。在哪里'bad'

h['good']=['fine','dandy']
h['bad'].push('unhappy')
h # => {"good"=>["fine", "dandy"]}

'bad'如果我们明确询问,就会出现。

h['bad'] # => ["alright", "unhappy"]

为什么显示哈希时不显示修改后的默认值?

4

2 回答 2

11

Hash 的默认值不像你期望的那样工作。当你说h[k]时,过程是这样的:

  1. 如果我们有一个k键,则返回它的值。
  2. 如果我们有哈希的默认值,则返回该默认值。
  3. 如果我们有一个提供默认值的块,则执行该块并返回其返回值。

请注意,(2) 和 (3) 对插入kHash 没有任何说明。默认值本质上变成h[k]了这样:

h.has_key?(k) ? h[k] : the_default_value

因此,简单地访问一个不存在的键并取回默认值不会将丢失的键添加到哈希中。

此外,任何形式的:

Hash.new([ ... ])
# or
Hash.new({ ... })

几乎总是一个错误,因为您将为所有默认值共享完全相同的默认数组或哈希。例如,如果您这样做:

h = Hash.new(['a'])
h[:k].push('b')

然后h[:i], h[:j], ... 将全部返回['a', 'b'],而这很少是您想要的。

我认为您正在寻找默认值的块形式

h = Hash.new { |h, k| h[k] = [ 'alright' ] }

这将做两件事:

  1. 访问不存在的键会将该键添加到 Hash 中,并将提供的 Array 作为其值。
  2. 所有默认值都将是不同的对象,因此更改一个不会更改其余的。
于 2012-02-29T03:13:32.260 回答
2

发生的事情是您通过push将'unhappy'修改为h['bad']. 您没有做的实际上是在哈希中添加了“坏”,这就是为什么在您检查时它没有出现的原因h

在您提供了所有代码之后,我尝试了这个:

>> p h['bleh']
=> ["allright", "unhappy"]

这肯定向我表明默认值已更改。在回答您的问题“为什么显示哈希时未显示修改后的默认值?”时,您必须向其中添加一个元素,而不仅仅是访问它:

>> h['bleh']  # Doesn't add 'bleh' to the hash
>> p h
=> {"good"=>["fine", "dandy"]} # See, no extra values

>> h['bleh'] = h.default  # Does add a new key with the default value
>> p h
=> {"good"=>["fine", "dandy"], "bleh"=>["allright", "unhappy"]}
于 2012-02-29T03:10:20.477 回答