Ruby Hash添加对象数组后显示为空,但元素可访问的原因咨询
为什么Hash.new([])赋值后哈希为空却能访问值?
这是个非常经典的Ruby哈希默认值“陷阱”,我来帮你把问题拆解明白:
问题的核心原因
当你用Hash.new []创建哈希时,你其实做了两件关键的事:
- 创建了一个单一的空数组对象,作为所有不存在键的默认返回值;
- 最关键的点:当你执行
@hash[a][0] = b时,你只是修改了那个共享的默认数组,根本没有给哈希本身添加任何键值对!
你修改的是默认数组的内容,但哈希@hash的键集合里从来没加入过a这个键。这就是为什么@hash.size是0、打印哈希显示{}——因为哈希确实没有存储任何键值对。
那为什么能访问到值呢?当你调用@hash[a]时,Ruby发现a不在哈希的键里,就会返回那个预先定义好的默认数组,而你之前已经给这个数组的索引0赋值了b,所以能看到对应的结果,但这一切和哈希本身的存储毫无关系。
正确的解决方法
想要实现“每个新键自动关联独立空数组,且键会被添加到哈希中”,你需要用块形式的Hash.new:
class Test def initialize # 块形式:每次访问不存在的键时,创建新数组并关联到该键 @hash = Hash.new { |h, k| h[k] = [] } end def run a = Object.new b = Object.new @hash[a][0] = b puts @hash # 输出包含键值对的哈希 puts @hash.size # 输出1 puts @hash[a].inspect # 输出 [#<Object:0x...>] puts @hash[a][0].inspect # 输出 #<Object:0x...> end end test = Test.new test.run
两种默认值方式的本质区别
Hash.new(obj):所有不存在的键都返回同一个obj实例,不会自动将键添加到哈希中;Hash.new { |h, k| h[k] = [] }:每次访问不存在的键时,执行块内代码,为该键创建新的数组并关联,同时将键加入哈希,每个键的数组都是完全独立的。
这样修改后,你的哈希就能正常存储键值对,size也会正确反映存储的元素数量,同时避免了多个键共享同一个数组的潜在问题。
内容的提问来源于stack exchange,提问作者b-wick
相关产品推荐
相关产品推荐

