这与Ruby hash default value behavior
有关但也许那里的解释ä¸åŒ…括这一部分:看æ¥Rubyçš„Hashé»˜è®¤å€¼æ˜¯ç‹¬ç«‹çš„ï¼Œæ— è®ºä½ æ˜¯â€œè¯»å®ƒâ€ï¼Œè¿˜æ˜¯çœ‹â€œè®¾ç½®ä»€ä¹ˆâ€ï¼Ÿ
一个例å是:
foo = Hash.new([])
foo[123].push("hi")
p foo # => {}
p foo[123] # => ["hi"]
p foo # => {}
foo[123]
如何有一个值,但是foo
都是空的,有点超出我的ç†è§£......我能ç†è§£çš„唯一方法是Ruby Hashä¿ç•™ä¸€ä¸ªå•ç‹¬çš„列表“读â€æˆ–“å¸æ°”â€ï¼Œä½†ä¸çŸ¥ä½•æ•…,“内部â€æŒ‡å®šå€¼æ˜¯ä¸åŒçš„。
如果Ruby的设计原则之一是“给程åºå‘˜å¸¦æ¥æœ€å°‘的惊喜â€ï¼Œé‚£ä¹ˆfoo
是空的,但foo[123]
是æŸç§ä¸œè¥¿ï¼Œåœ¨æŸç§ç¨‹åº¦ä¸Šæ˜¯è¿™æ ·çš„,对于我
(实际上我还没有看到其他è¯è¨€...如果有其他è¯è¨€æœ‰ç±»ä¼¼è¡Œä¸ºçš„情况,也许更容易建立è”系。)
ç”案 0 :(得分:3)
å‡è®¾`
h = Hash.new(:cat)
h[:a] = 1
h[:b] = 2
h #=> {:a=>1, :b=>2}
现在
h[:a] #=> 1
h[:b] #=> 2
h[:c] #=> :cat
h[:d] #=> :cat
h #=> {:a=>1, :b=>2}
h = Hash.new(:cat)
使用h
的默认值定义空哈希:cat
。这æ„味ç€ï¼Œå¦‚æžœh
没有密钥k
,则h[k]
将返回:cat
,仅返回。如上所示,当h[k]
为k
或:c
时,执行:d
ä¸ä¼šæ›´æ”¹å“ˆå¸Œå€¼ã€‚
å¦ä¸€æ–¹é¢ï¼Œ
h[:c] = h[:c]
#=> :c
h #=> {:a=>1, :b=>2, :c=>:cat}
困惑?让我在没有è¯æ³•ç³–的情况下写这个:
h.[]=(:d, h.[](:d))
#=> :cat
h #=> {:a=>1, :b=>2, :d=>:cat}
默认值由h.[](:d)
返回(å³h[:d]
),而Hash#[]=
是一个赋值方法(带有两个å‚数,一个键和一个值),默认值为ä¸é€‚用。
æ¤é»˜è®¤è®¾ç½®çš„常è§ç”¨æ³•æ˜¯åˆ›å»ºè®¡ç®—哈希:
a = [1,3,1,4,2,5,4,4]
h = Hash.new(0)
a.each { |x| h[x] = h[x] + 1 }
h #=> {1=>2, 3=>1, 4=>3, 2=>1, 5=>1}
最åˆï¼Œå½“h
为空且x #=> 1
时,h[1] = h[1] + 1
将评估为h[1] = 0 + 1
ï¼Œå› ä¸ºï¼ˆå› ä¸ºh
没有密钥1
)ç‰å¼å³ä¾§çš„h[1]
设置为ç‰äºŽé»˜è®¤å€¼é›¶ã€‚下次1
ä¼ é€’ç»™å—x #=> 1
),x[1] = x[1] + 1
,ç‰äºŽx[1] = 1 + 1
ã€‚è¿™æ¬¡æ²¡æœ‰ä½¿ç”¨é»˜è®¤å€¼ï¼Œå› ä¸ºh
现在有一个键1
。
通常会写(顺便说一å¥ï¼‰ï¼š
a.each_with_object(Hash.new(0)) { |x,h| h[x] += 1 }
#=> {1=>2, 3=>1, 4=>3, 2=>1, 5=>1}
通常ä¸å¸Œæœ›é»˜è®¤å€¼æ˜¯é›†åˆï¼Œä¾‹å¦‚数组或散列。请考虑以下事项:
h = Hash.new([])
[1,2,3].map { |n| h[n] = h[n] }
h #=> {1=>[], 2=>[], 3=>[]}
现在观察:
h[1] << 2
h #=> {1=>[2], 2=>[2], 3=>[2]}
这通常ä¸æ˜¯ç†æƒ³çš„行为。它å‘ç”Ÿäº†ï¼Œå› ä¸º
h.map { |k,v| v.object_id }
#=> [25886508, 25886508, 25886508]
也就是说,所有值都是åŒä¸€ä¸ªå¯¹è±¡ï¼Œå› æ¤å¦‚果更改了一个键的值,则所有其他键的值也会更改。
解决这个问题的方法是在定义哈希时使用å—:
h = Hash.new { |h,k| h[k]=[] }
[1,2,3].each { |n| h[n] = h[n] }
h #=> {1=>[], 2=>[], 3=>[]}
h[1] << 2
h #=> {1=>[2], 2=>[], 3=>[]}
h.map { |k,v| v.object_id }
#=> [24172884, 24172872, 24172848]
当散列h
没有键k
时,å—{ |h,k| h[k]=[] }
被执行并返回一个特定于该键的空数组。
ç”案 1 :(得分:2)
声明:
foo = Hash.new([])
creates a new Hash,其数组为空([]
为默认值)。默认值是Hash::[]
在其å‚æ•°ä¸æ˜¯æ•£åˆ—ä¸å˜åœ¨çš„键时返回的值。
声明:
foo[123]
调用Hash::[]
ï¼Œå› ä¸ºå“ˆå¸Œæ˜¯ç©ºçš„ï¼ˆå“ˆå¸Œä¸ä¸å˜åœ¨é”®123
),它返回对默认值的引用,该默认值是{{3}类型的对象}。
上é¢çš„è¯å¥ä¸ä¼šåœ¨å“ˆå¸Œä¸åˆ›å»º123
键。
Rubyå¯¹è±¡æ€»æ˜¯é€šè¿‡å¼•ç”¨ä¼ é€’å’Œè¿”å›žã€‚è¿™æ„味ç€ä¸Šé¢çš„è¯å¥ä¸ä¼šè¿”回散列的默认值的副本,而是返回对它的引用。
声明:
foo[123].push("hi")
修改上é¢æ到的数组。现在,foo
哈希的默认值ä¸å†æ˜¯ç©ºæ•°ç»„;它是数组["hi"]
。但是ä»ç„¶æ˜¯ç©ºçš„;以上所有è¯å¥éƒ½æ²¡æœ‰æ·»åŠ 一些(键,值)对。
 Âfoo [123]如何具有值
foo[123]
没有任何值,哈希ä¸ä¸å˜åœ¨é”®123
(哈希为空)。éšåŽå¯¹foo[123]
的调用会å†æ¬¡è¿”回对默认值的引用,现在返回默认值["hi"]
。对foo[456]
或foo['abc']
的调用也会返回对相åŒé»˜è®¤å€¼çš„引用。
ç”案 2 :(得分:0)
您实际上并未更改密钥123的值,您åªæ˜¯è®¿é—®åˆå§‹åŒ–期间æ供的默认值[]
。如果您检查foo[0]
ç‰å…¶ä»–值,则å¯ä»¥ç¡®è®¤è¿™ä¸€ç‚¹ã€‚
å¦‚æžœä½ è¿™æ ·åšï¼š
foo[123] = ["hi"]
您å¯ä»¥çœ‹åˆ°æ–°æ¡ç›®ï¼Œå› 为您已在密钥123下创建了一个新数组。
修改的
当您致电foo[123].push("hi")
时,您改å˜ï¼ˆé»˜è®¤ï¼‰å€¼ï¼Œè€Œä¸æ˜¯æ·»åŠ æ–°æ¡ç›®ã€‚
调用foo[123] += ["hi"]
会在给定密钥下创建一个新数组,替æ¢ä¹‹å‰å˜åœ¨çš„数组,这将显示您想è¦çš„行为。
ç”案 3 :(得分:0)
打å°å“ˆå¸Œï¼š
p foo
仅打å°å˜å‚¨åœ¨å“ˆå¸Œä¸çš„值。它ä¸æ˜¾ç¤ºé»˜è®¤å€¼ï¼ˆæˆ–æ·»åŠ åˆ°é»˜è®¤æ•°ç»„çš„ä»»ä½•å†…å®¹ï¼‰ã€‚
执行时:
p foo[123]
å› ä¸º123ä¸å˜åœ¨ï¼Œæ‰€ä»¥å®ƒè®¿é—®é»˜è®¤å€¼ã€‚
å¦‚æžœæ‚¨å°†ä¸¤ä¸ªå€¼æ·»åŠ åˆ°é»˜è®¤å€¼ï¼š
foo[123].push("hi")
foo[456].push("hello")
您的输出将是:
p foo # => {}
p foo[123] # => ["hi","hello"]
p foo # => {}
这里,poo [123]å†æ¬¡ä¸å˜åœ¨ï¼Œæ‰€ä»¥å®ƒæ‰“å°å‡ºé»˜è®¤å€¼çš„内容。