哈希值和`<<`运算符之间的交互

时间:2018-12-04 13:41:41

标签: ruby hash

我期望:

h = Hash.new([])
h['a'] << 'b'
h['a'] << 'c'
h # => {}

给出{'a' => ['b','c']},而不是空哈希。

我还发现插入操作将默认值作为目标,因为上面的代码在['b','c']之后是必需的:

h.default # => ['b','c']

我正在寻找一种解释,为什么它不起作用以及如何最佳地使它起作用。

3 个答案:

答案 0 :(得分:7)

您的行不起作用的原因是Hash在访问丢失的密钥时,仅返回默认值(无论您指定了什么),而没有将其分配给密钥。并且由于您的默认值是一个复杂的可变对象(并且每次都返回相同的对象),因此您将获得所观察到的结果:所有值都被直接铲成默认值,绕过了哈希。这可能是哈希和可变默认值最常见的错误。

要执行所需操作,请使用Hash.new的第三种形式

new {|hash, key| block } → new_hash

例如,

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

答案 1 :(得分:0)

这是因为您修改了作为默认值传递的特定对象。所以:

h = Hash.new([])
h['a'] << 'b'
h['a'] << 'c'
h['b'] # or h['a'] or h[:virtually_anything]
# => ["b", "c"]

答案 2 :(得分:0)

这是因为h没有密钥'a',您需要先对其进行初始化,或者仅将其重置为默认值即可。

h = Hash.new([])
h['a'] = ['b']
h['a'] << 'c'

h['a'] #=> ["b", "c"]
h #=> {"a"=>["b", "c"]}

行为相同:

k = Hash.new
k.default = []

正如Sergio Tulentsev(https://stackoverflow.com/a/53614695/5239030)所解释的那样,它创建了“即时”密钥,请尝试以下操作:

k = Hash.new {|h, k| puts "Just created a new key: #{k}"; h[k] = [] }
p k['a'] << 'a'
p k['a'] << 'a'
p k['b'] << 'b'
p k