我是Ruby的新手并且正在运行Ruby Koans。在Ruby Koans的about_hashes.rb文件中,有一个为散列分配默认值的示例。
hash = Hash.new([])
hash[:one] << "uno"
hash[:two] << "dos"
puts hash[:one] # this is ["uno", "dos"]
这里hash[:one]
&amp; hash[:two]
或任何类似hash[:three]
的键(非现有键)都具有值[“uno”和“dos”]我不明白“&lt;&lt;”在这里使用。此外,当我尝试提取键和&amp;哈希值,或打印键/值,它是空的。
puts (hash.values.size) # size is 0 here
puts (hash.keys.size) # size is 0
puts hash.values # nothing gets printed
puts hash.keys #nothing gets printed.
那么这里发生了什么?存储的值在哪里,如果它们没有作为键或值存储在散列中。
在下一个例子中,当Hash定义为
时hash = Hash.new {|hash, key| hash[key] = [] }
hash[:one] << "uno"
hash[:two] << "dos"
puts hash[:one] #this is "uno"
puts hash[:two] #this is "dos"
puts hash[:three] # this is undefined.
我想在第二个例子中,hash正在使用空白数组初始化所有键。因此当“&lt;&lt;”时,“uno”会被附加到空数组中使用此运算符?我对这两个例子感到困惑。我不知道他们俩发生了什么。我也无法在谷歌中找到关于这个例子的更多信息。如果有人可以帮我解释这两个例子,那将会很有帮助。提前致谢
答案 0 :(得分:4)
<强> hash = Hash.new([])
强>
此语句创建一个空哈希,其默认值为空数组。如果hash
没有密钥k
,则hash[k]
会返回默认值[]
。这很重要:只需返回默认值不修改哈希值。
当你写:
hash[:one] << "uno" #=> ["uno"]
在hash
有一个键:one
之前,hash[:one]
被默认值替换,所以我们有:
[] << "uno" #=> ["uno"]
解释了为什么hash
没有改变:
hash #=> {}
现在写:
hash[:two] << "dos" #=> ["uno", "dos"]
hash #=> {}
为了了解我们得到此结果的原因,请按以下步骤重写以上内容:
hash = Hash.new([]) #=> {}
hash.default #=> []
hash.default.object_id #=> 70209931469620
a = (hash[:one] << "uno") #=> ["uno"]
a.object_id #=> 70209931469620
hash.default #=> ["uno"]
b = (hash[:two] << "dos") #=> ["uno", "dos"]
b.object_id #=> 70209931469620
hash.default #=> ["uno", "dos"]
因此,您可以看到object_id
为70209931469620
的默认数组是&#34; uno&#34;和&#34; dos&#34;附加。
如果我们写了:
hash[:one] = hash[:one] << "uno"
#=> hash[:one] = [] << "uno" => ["uno"]
hash #=> { :one=>"uno" }
我们得到了我们希望的东西,但不是那么快:
hash[:two] = hash[:two] << "dos"
#=> ["uno", "dos"]
hash
#=> {:one=>["uno", "dos"], :two=>["uno", "dos"]}
仍然不是我们想要的,因为两个键的值都是相同的数组。
<强> hash = Hash.new {|hash, key| hash[key] = [] }
强>
当hash
没有密钥key
时,此语句会导致执行该块。此 通过添加键值对 1 来更改哈希值。
现在:
hash[:one] << "uno"
导致阻止:
{ |h,k| h[k] = [] }
进行作业:
hash[:one] = []
之后:
hash[:one] << "uno"
将"uno"
附加到一个空数组,该数组是键:one
的值,我们可以验证:
hash #=> { :one=>"uno" }
这与写作具有相同的效果:
hash[:one] = (hash[:one] || []) << "uno"
((hash[:one] ||= []) << "uno"
的扩展版本),当没有默认值时。
类似地,
hash[:two] << "dos" #=> ["dos"]
hash #=> {:one=>["uno"], :two=>["dos"]}
这通常是我们想要的结果。
1但是,块不需要更改哈希值。该块可以包含任何代码,例如{ puts "Have a nice day" }
。
答案 1 :(得分:3)
hash = Hash.new(INITIAL_VALUE)
是用于创建哈希的语法,具有默认值。默认值是整个散列本身的“属性”,当访问不存在的密钥时,它将被返回。
所以,在你的第一个例子中:
hash = Hash.new([]) # return a reference to an empty array for unknown keys
与:
相同initial = []
hash = Hash.new(initial)
因此,当你打电话:
hash[:one] << "uno"
您实际上致电hash[:one]
,返回initial
,然后在其上调用#<<
方法。换句话说,这些后续调用与:
initial << "uno"
initial << "dos"
我想,现在很清楚,为什么所有人都在分享相同的价值。哈希本身仍然是空的(在上面的任何调用中,正在使用initial
。)看:
hash.merge! { one: "uno", three: "tres" }
hash[:one] # defined, since merge above
#⇒ "uno"
hash[:two] # undefined, initial will be returned
#⇒ []
hash[:two] << 'dos'
hash[:two] # defined, but defined as a reference to initial
#⇒ ["dos"]
hash[:two] = 'zwei' # redefined
#⇒ "zwei"
hash[:four] # undefined, initial
#⇒ ["dos"]
希望它有所帮助。