我正在v2.3.7中尝试Ruby的默认Hash值。我对一个简单的测试用例中的输出感到惊讶,并且我想知道幕后发生的事情可以解释它。
foo = Hash.new({x: 0, y: 0}) # provide a default value
foo['bar'][:x] += 1 # expect to add to the default value
foo # outputs `{}` ?! expected {'bar'=>{:x=>1,:y=>0}}
foo['bar'] # outputs `{:x=>1, :y=>0}` as expected
为什么foo
在第3行上似乎为空?我期望像{'bar'=>{:x=>1,:y=>0}}
这样的输出。我是否缺少关于这种情况发生的超级基础知识? foo.empty?
返回true
,但是foo['bar']
产生输出。
这是一个错误吗?
答案 0 :(得分:3)
使用默认值时,未设置键/值。仅返回默认值而不是nil
。
我想您正在想象它的工作原理,其中对||=
之类的访问键设置了默认值。
default = {x: 0, y: 0}
foo = Hash.new
foo['bar'] ||= default
foo['bar'][:x] += 1
相反,它的工作原理是在没有密钥的情况下返回默认值。
default = {x: 0, y: 0}
foo = Hash.new
val = foo['bar'] || default
val[:x] += 1
换一种说法,您期望如此。
def [](key)
@data[key] ||= default
end
但是它是这样的。
def [](key)
@data[key] || default
end
但是,如果我提供一个整数而不是一个Hash作为默认值,则此行为似乎会改变。例如,如果我执行foo = Hash.new(1),则foo ['bar'] + = 1则是我所期望的行为。 foo不为空,并且默认值未更改。 – 4分钟前aardvarkk
foo['bar'] += 1
确实是速记
default = foo['bar'] # fetch the default
foo['bar'] = default + 1 # sets 'bar' on foo
请注意,它将在[]=
上调用foo
。
foo['bar'][:x] += 1
是...的简写。
default = foo['bar'] # fetch the default value
val = default[:x] # fetch :x from the default
default[:x] = val + 1 # set :x on the default value
请注意,它以默认值而不是[]=
调用foo
。
答案 1 :(得分:2)
基本上,您正在更改默认值,而不是将新密钥分配给哈希。 可以通过调用哈希的任何键来理解,例如
foo['bar']
=> {:x=>1, :y=>0}
foo['foobar']
=> {:x=>1, :y=>0}
另一种查看方式
foo['bar'][:x] += 1
=> 2
foo['bar']
=> {:x=>2, :y=>0}
foo['bar'][:x] += 1
=> 3
foo['bar']
=> {:x=>3, :y=>0}
foo['bar'][:x] + 1
=> 4
foo['bar']
=> {:x=>3, :y=>0} # here the value is not assigned so not changed - as expected
答案 2 :(得分:0)
法汉·梅蒙(Farhan Memon)博士已经提到:
基本上,您正在更改默认值且未分配新密钥 散列。
但这将返回您想要的内容:
foo = Hash.new({x: 0, y: 0}) # provide a default value
foo[:whatever][:x] += 1
foo['bar'] = foo['bar']
foo #=> {"bar"=>{:x=>1, :y=>0}}
首先,您更改了默认值,然后将默认值分配给新键['bar']
。也可以与foo['bar'] = foo[:whatever_else]
一起使用。
foo['bar'] = foo[:whatever_else]
foo['baz'] = foo[:whatever_else]
foo #=> {"bar"=>{:x=>1, :y=>0}, "baz"=>{:x=>1, :y=>0}}