我有以下小序列,这对我没有意义:
irb(main):001:0> h = {}
=> {}
irb(main):002:0> h.default = {}
=> {}
irb(main):003:0> h["foo"]["bar"] = 6
=> 6
irb(main):004:0> h.length
=> 0
irb(main):005:0> h.keys
=> []
irb(main):006:0> h["foo"]
=> {"bar"=>6}
第5步是如何返回一个空的键列表,第4步表示h
的长度是0
,但我可以在步骤6中看到"foo"
是一个有效密钥并具有关联值。我希望keys
返回["foo"]
,length
返回1
。
我误解了什么?注意这是Ruby 1.9.3p0
另请注意,此操作正常:
irb(main):001:0> h = {}
=> {}
irb(main):002:0> h["foo"] = {}
=> {}
irb(main):003:0> h["foo"]["bar"] = 6
=> 6
irb(main):004:0> h.length
=> 1
irb(main):005:0> h.keys
=> ["foo"]
irb(main):006:0> h["foo"]
=> {"bar"=>6}
唯一的区别是使用Hash.default来设置默认值并跳过h["foo"]
的显式初始化。这是一个错误吗?
答案 0 :(得分:2)
行*Main> freeVars (Var "e")
["e"]
*Main> freeVars (Lam "e" (Var "x"))
["x"]
*Main> freeVars (Lam "e" (Var "e"))
[]
*Main> freeVars (App (Lam "e" (Var "x")) (Nat 3))
["x"]
*Main> freeVars (App (Lam "e" (Var "e")) (Nat 3))
[]
表示在缺少密钥时返回的默认值为$(function () {
$('#container-speed').highcharts(Highcharts.merge({},
{
"colors": [
"#4FB04F"
],
"yAxis": {
"min": 0,
"max": 200500500,
"tickPositions": [
0,
150500500,
200500500
],
"labels": {
"y": 24,
"style": {
"color": "#0e4d5c"
}
},
"lineWidth": 0,
"minorTickInterval": null,
"tickWidth": 0,
"title": {
"enabled": false
}
},
"series": [
{
"name": "Speed",
"data": [
150500500
]
}
],
"chart": {
"type": "solidgauge",
"height": 190
},
"title": {
"text": ""
},
"pane": {
"center": [
"50%",
"125%"
],
"size": "240%",
"startAngle": -70,
"endAngle": 70,
"background": {
"backgroundColor": "#0e4d5c",
"borderWidth": 0,
"innerRadius": "81%",
"outerRadius": "92%",
"shape": "arc"
}
},
"tooltip": {
"enabled": false
},
"plotOptions": {
"solidgauge": {
"innerRadius": "88%",
"radius": "85%",
"dataLabels": {
"enabled": false
}
}
},
"credits": {
"enabled": false
}
}));
});
。此外,将返回此特定哈希实例。
第h.default = {}
行查找键{}
,当它无法找到时,它会获取默认值h["foo"]["bar"] = 6
并在其中插入键foo
}和值{}
。在此之后哈希仍然是空的。
这就是您看到这些结果的原因。
您也可以使用default_proc来设置密钥。
答案 1 :(得分:1)
您只需设置默认值,如果未找到任何值,将返回该值。这并没有改变没有为h["foo"]
分配值的事实。 {"bar"=>6}
将是未找到的任何密钥的值。
h = {}
h.default = {} # => {}
h["foo"]["bar"] = 6 # => 6
h["foo"] # => {"bar"=>6}
h["baz"] # => {"bar"=>6}
如果你想要一个返回的哈希并将缺失键的值设置为空哈希,你必须这样做:
h = Hash.new { |hash, key| hash[key] = {} }
h["foo"]["bar"] = 6 # => 6
h # => {:foo=>{:bar=>6}}
答案 2 :(得分:0)
默想:
h={} #=> {}
h['foo'] #=> nil
由于['foo']
不存在,尝试访问它会导致结果为零。这意味着尝试访问'foo'
的子哈希将失败:
h['foo']['bar']
NoMethodError: undefined method `[]' for nil:NilClass
这相当于使用:
nil['bar']
NoMethodError: undefined method `[]' for nil:NilClass
我们可以通过定义h['foo']
是什么来解决这个问题:
h['foo'] = {} #=> {}
它是定义的,所以当我们请求它的值时,我们得到一个空哈希:
h['foo'] #=> {}
现在h['foo']['bar']
将返回预期的内容,为零:
h['foo']['bar'] # => nil
此时,h['foo']['bar']
的作业将有意义:
h['foo']['bar'] = 6
看着h
表明我们有哈希哈希:
h # => {"foo"=>{"bar"=>6}}
使用h.default = {}
尝试解决h['foo']
返回nil的问题:
h = {}
h.default = {}
h # => {}
h['foo'] # => {}
而且,是的,它确实如此,但它也引入了一个主要问题。我们希望哈希值能够一致地返回密钥的值,但是h.default = {}
已经设置了问题。通常我们希望哈希行为如下:
h = {}
h # => {}
h['foo'] = {}
h['bar'] = {}
h # => {"foo"=>{}, "bar"=>{}}
h['foo']['baz'] = 1
h['bar']['baz'] = 2
h # => {"foo"=>{"baz"=>1}, "bar"=>{"baz"=>2}}
h['foo'].object_id # => 70179045516300
h['bar'].object_id # => 70179045516280
h['foo']['baz'].object_id # => 3
h['bar']['baz'].object_id # => 5
使用h.default = {}
打破了这一点。我们知道存在h['foo']
,我们希望h['bar']
不存在或指向内存中不同的键/值对,但它不会:
h = {}
h.default = {}
h # => {}
h['foo']['baz'] = 1
h['bar']['baz'] = 2
h # => {}
h['foo'].object_id # => 70142994238340
h['bar'].object_id # => 70142994238340
h['foo']['baz'] # => 2
h['bar']['baz'] # => 2
h['foo']['baz'].object_id # => 5
h['bar']['baz'].object_id # => 5
你真的不希望这种情况发生,因为它是完全陌生和意想不到的行为,这将使你的代码以奇怪和奇妙的方式打破,再加上让你讨厌维护/调试你的其他人代码。
整个问题是h.default = {}
的使用,因为它并不意味着“总是使用新的哈希”,这意味着“总是使用这个哈希”。
相反,像这样的东西可以解决问题:
h = Hash.new{ |hash,key| hash[key] = Hash.new(&hash.default_proc) }
h['foo']['baz'] = 1
h['bar']['baz'] = 2
h # => {"foo"=>{"baz"=>1}, "bar"=>{"baz"=>2}}
h['foo'].object_id # => 70109399098340
h['bar'].object_id # => 70109399098320
h['foo']['baz'] # => 1
h['bar']['baz'] # => 2
h['foo']['baz'].object_id # => 3
h['bar']['baz'].object_id # => 5
此时,散列应该按预期运行,没有人会想要追捕你。这个解决方案有一些问题,但它是一个更好的构建块。有关详细信息,请参阅“Dynamically creating a multi-dimensional hash in Ruby”。