修改默认哈希值

时间:2012-02-29 02:44:52

标签: ruby hash invisible

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"]

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

2 个答案:

答案 0 :(得分:11)

哈希的默认值不像你期望的那样工作。当你说h[k]时,过程如下:

  1. 如果我们有k密钥,请返回其值。
  2. 如果我们有Hash的默认值,则返回该默认值。
  3. 如果我们有一个提供默认值的块,请执行该块并返回其返回值。
  4. 请注意,(2)和(3)没有说明将k插入哈希。默认值基本上将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'],这很少是你想要的。

    我认为你正在寻找block form of the default value

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

    这将做两件事:

    1. 访问不存在的密钥会将该密钥添加到哈希,并且它将提供的数组作为其值。
    2. 所有默认值都是不同的对象,因此更改其中一个不会改变其余对象。

答案 1 :(得分:2)

发生的事情是你已经修改了哈希的默认值,push'不快'到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"]}