This question already has an answer here:
这个问题在这里已有答案:
- Strange, unexpected behavior (disappearing/changing values) when using Hash default value, e.g. Hash.new([]) 4 answers
使用哈希默认值时出现奇怪的意外行为(消失/更改值),例如: Hash.new([])4个答案
Ruby lets you define default values for hashes:
Ruby允许您为哈希定义默认值:
h=Hash.new(['alright'])
h['meh'] # => ["alright"]
Assignment of a value shows up when displaying the hash, but a modified default does not. Where's 'bad'
?
显示散列时会显示值的赋值,但修改后的默认值不会。哪里'糟糕'?
h['good']=['fine','dandy']
h['bad'].push('unhappy')
h # => {"good"=>["fine", "dandy"]}
'bad'
shows up if we explicitly ask.
如果我们明确要求,'坏'会出现。
h['bad'] # => ["alright", "unhappy"]
Why does the modified default value not show up when displaying the hash?
为什么在显示哈希时不会显示修改后的默认值?
2 个解决方案
#1
11
Hash's default value doesn't work like you're expecting it to. When you say h[k]
, the process goes like this:
哈希的默认值不像你期望的那样工作。当你说h [k]时,过程如下:
- If we have a
k
key, return its value. - If we have a default value for the Hash, return that default value.
- If we have a block for providing default values, execute the block and return its return value.
如果我们有一个k键,则返回其值。
如果我们有Hash的默认值,则返回该默认值。
如果我们有一个用于提供默认值的块,请执行该块并返回其返回值。
Note that (2) and (3) say nothing at all about inserting k
into the Hash. The default value essentially turns h[k]
into this:
注意,(2)和(3)没有说明将k插入哈希。默认值实质上将h [k]变为:
h.has_key?(k) ? h[k] : the_default_value
So simply accessing a non-existant key and getting the default value back won't add the missing key to the Hash.
因此,只需访问一个不存在的密钥并获取默认值就不会将缺少的密钥添加到哈希中。
Furthermore, anything of the form:
此外,任何形式:
Hash.new([ ... ])
# or
Hash.new({ ... })
is almost always a mistake as you'll be sharing exactly the same default Array or Hash for for all default values. For example, if you do this:
几乎总是一个错误,因为你将为所有默认值共享完全相同的默认数组或哈希值。例如,如果您这样做:
h = Hash.new(['a'])
h[:k].push('b')
Then h[:i]
, h[:j]
, ... will all return ['a', 'b']
and that's rarely what you want.
然后h [:i],h [:j],...将全部返回['a','b'],这很少是你想要的。
I think you're looking for the block form of the default value:
我想你正在寻找默认值的块形式:
h = Hash.new { |h, k| h[k] = [ 'alright' ] }
That will do two things:
这将做两件事:
- Accessing a non-existent key will add that key to the Hash and it will have the provided Array as its value.
- All of the default values will be distinct objects so altering one will not alter the rest.
访问不存在的密钥会将该密钥添加到哈希,并且它将提供所提供的数组作为其值。
所有默认值都是不同的对象,因此更改一个不会改变其余的对象。
#2
2
What's happened is that you have modified the default value of the hash, by push
ing 'unhappy' onto h['bad']
. What you haven't done is actually added 'bad' to the hash, which is why it doesn't show up when you inspect h
.
发生的事情是你通过将'unhappy'推到h ['bad']来修改哈希的默认值。你没有做的实际上是在哈希中添加了“坏”,这就是为什么当你检查h时它不会出现。
After all the code you supplied, I tried this:
在您提供的所有代码之后,我尝试了这个:
>> p h['bleh']
=> ["allright", "unhappy"]
Which certainly suggests to me that the default value has been changed. In answer to your question 'Why does the modified default not show up when displaying the hash?', you would have to add an element to it, rather than just accessing it:
这肯定告诉我默认值已经改变。在回答你的问题'为什么修改后的默认值不会在显示哈希时显示?'时,你必须向它添加一个元素,而不是仅仅访问它:
>> 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
11
Hash's default value doesn't work like you're expecting it to. When you say h[k]
, the process goes like this:
哈希的默认值不像你期望的那样工作。当你说h [k]时,过程如下:
- If we have a
k
key, return its value. - If we have a default value for the Hash, return that default value.
- If we have a block for providing default values, execute the block and return its return value.
如果我们有一个k键,则返回其值。
如果我们有Hash的默认值,则返回该默认值。
如果我们有一个用于提供默认值的块,请执行该块并返回其返回值。
Note that (2) and (3) say nothing at all about inserting k
into the Hash. The default value essentially turns h[k]
into this:
注意,(2)和(3)没有说明将k插入哈希。默认值实质上将h [k]变为:
h.has_key?(k) ? h[k] : the_default_value
So simply accessing a non-existant key and getting the default value back won't add the missing key to the Hash.
因此,只需访问一个不存在的密钥并获取默认值就不会将缺少的密钥添加到哈希中。
Furthermore, anything of the form:
此外,任何形式:
Hash.new([ ... ])
# or
Hash.new({ ... })
is almost always a mistake as you'll be sharing exactly the same default Array or Hash for for all default values. For example, if you do this:
几乎总是一个错误,因为你将为所有默认值共享完全相同的默认数组或哈希值。例如,如果您这样做:
h = Hash.new(['a'])
h[:k].push('b')
Then h[:i]
, h[:j]
, ... will all return ['a', 'b']
and that's rarely what you want.
然后h [:i],h [:j],...将全部返回['a','b'],这很少是你想要的。
I think you're looking for the block form of the default value:
我想你正在寻找默认值的块形式:
h = Hash.new { |h, k| h[k] = [ 'alright' ] }
That will do two things:
这将做两件事:
- Accessing a non-existent key will add that key to the Hash and it will have the provided Array as its value.
- All of the default values will be distinct objects so altering one will not alter the rest.
访问不存在的密钥会将该密钥添加到哈希,并且它将提供所提供的数组作为其值。
所有默认值都是不同的对象,因此更改一个不会改变其余的对象。
#2
2
What's happened is that you have modified the default value of the hash, by push
ing 'unhappy' onto h['bad']
. What you haven't done is actually added 'bad' to the hash, which is why it doesn't show up when you inspect h
.
发生的事情是你通过将'unhappy'推到h ['bad']来修改哈希的默认值。你没有做的实际上是在哈希中添加了“坏”,这就是为什么当你检查h时它不会出现。
After all the code you supplied, I tried this:
在您提供的所有代码之后,我尝试了这个:
>> p h['bleh']
=> ["allright", "unhappy"]
Which certainly suggests to me that the default value has been changed. In answer to your question 'Why does the modified default not show up when displaying the hash?', you would have to add an element to it, rather than just accessing it:
这肯定告诉我默认值已经改变。在回答你的问题'为什么修改后的默认值不会在显示哈希时显示?'时,你必须向它添加一个元素,而不是仅仅访问它:
>> 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"]}