2012-02-29 121 views
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"] 

为什么修改后的默认值在显示散列时不显示?

+0

合法的问题,但它可能是重复的。 – 2012-02-29 22:44:10

回答

11

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

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

请注意,(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. 所有的默认值将是不同的对象,所以改变一个不会改变其余的。
2

发生什么事是你修改了散列的默认值,由push ing'不快乐'到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"]} 
+1

哇。我的立场完全纠正。但是现在我很难为这是为什么。 []是一个散列对象的方法,它返回一个结果。为什么要发送推送更改默认散列?开始挖掘ruby源代码的时间... – 2012-02-29 03:16:46

+0

明白了。哈希对象仍包含对正在更新的数组的引用。删除我的答案。 :) – 2012-02-29 03:20:56

+1

我假设默认值是传递给哈希的构造函数的数组的引用。当你'推'到那个,你直接修改阵列,而不是创建一个副本。举个简单的例子:'h = Hash.new('hello'); h ['something'] <<'aaa';把h.default'放回'helloaaa' – 2012-02-29 03:22:47