为什么将字符串铲入哈希会导致此结果?

时间:2017-10-11 20:48:01

标签: ruby

我正在使用Ruby Koans,以便更好地掌握Ruby和TDD。我在about_hashes.rb的代码中得到了第93行,这让我很困惑如何将它铲入默认构造函数而不是哈希值。出于好奇,我尝试使用与字符串相同的东西作为构造函数的参数,它产生了类似的结果。

现在我的问题是为什么,无论我使用什么密钥,都会检索相同的对象,以及如何在方法中的哈希中的特定键上将新对象铲入数组 {{1 }}的

test_default_value_is_the_same_object

2 个答案:

答案 0 :(得分:3)

原因在于测试名称。

test_default_value_is_the_same_object可以告诉您,当您要求hash[:some_value_that_doesnt_exist_yet]时,默认情况下会返回您指定的默认值 - 每个相同的对象时间。通过修改该对象,可以为每个不存在的键修改它。修改hash[:one]也会修改hash[:two]

test_default_value_with_block显示使用块构造哈希,该块将用于为每个键提供新值。当你这样做时,hash[:one]hash[:two]的值是不同的。

答案 1 :(得分:2)

当密钥不存在时,您已创建一个新的Hash,其中Array为累加器,因此

hash = Hash.new([]) 
hash[:one] << "uno" 
hash[:one] == ["uno"] #=> true

但是

hash[:two] << "dos" 
(hash[:one] == hash[:two]) && (hash[:two] == ["uno","dos"]) #=> true
hash[:three] == ["uno","dos"] #=> true

因为["uno","dos"]是使用Hashhash[:non_existant_key]指向它创建的原始数组。

注意:在这种情况下,hash实际上没有添加任何密钥。它类似于

 a = []
 hash = {}
 hash.fetch(:one,a) << 'uno'
 hash.fetch(:two,a) << 'dos'
 hash.fetch(:three, a) 
 #=> ['uno','dos']
 hash
 #=> {}

要解决此问题,您可以使用第二次测试中提到的语法

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

这意味着每个新密钥都会将新的Array实例化为其值,而不是一遍又一遍地重复使用相同的Array

Hash.new(obj)是一个可变对象时,这是obj语法的问题