正在学习使用 ruby 编写代码。我正在学习哈希,但我不明白这段代码:
count = Hash.new(0)
。它说 0 是默认值,但是当我在 irb 上运行它时,它给了我一个空的哈希值 {}。如果 0 是默认值,为什么我看不到类似 count ={0=>0}
的内容。或者零是累加器但不转到键或值?谢谢
0 将是后备
例如:
count = Hash.new
-> count['key'] => nil
对
count = Hash.new(0)
-> count['key'] => 0
扩展@jeremy-ramos 的答案和@mu-is-too-short 的评论。
通过这种方式有两个常见的默认哈希值问题。
Ruby 使用内存中的完全相同对象作为每个丢失键的默认值。
对于不可变对象(如
0
),没有问题。但是您可能想编写如下代码:
hash = Hash.new([])
hash[key] << value
或
hash = Hash.new({})
hash[key][second_key] = value
这不会达到您的预期。
hash[unknown_key]
不会返回新的空数组或哈希,而是为每个键返回完全相同的数组/哈希对象。
这样做:
hash = Hash.new([])
hash[key1] << value1
hash[key2] << value2
产生一个散列,其中
key1
和 key2
都指向包含 [value1, value2]
的同一个数组对象
请参阅此处相关问题
要解决此问题,您可以创建一个带有默认块参数的哈希(每当访问丢失的键时就会调用该哈希,并让您为丢失的键分配一个值)
hash = Hash.new{|h, key| h[key] = [] }
当您访问返回默认值的缺失键时,您可能期望哈希现在将包含该键以及返回的值。它不是。 Ruby 不会修改哈希值,它只是返回默认值。因此,例如:
hash = Hash.new(0) #$> {}
hash.keys.empty? #$> true
hash[:foo] #$> 0
hash[:foo] == 0 #$> true
hash #$> {}
hash.keys.empty? #$> true
使用块方法也可以解决这种混乱,可以显式设置它们的键值。
Hash.new
文档对此不是很清楚。我希望下面的示例能够阐明 Hash.new(0)
的区别和常用用法之一。
第一块代码使用
Hash.new(0)
。 hash的默认值为0,当遇到新的key时,其值为0。这个方法可以用来统计数组中的字符。
第二块代码失败,因为键的默认值(未分配时)是
nil
。该值不能用于加法(计数时),并且会产生错误。
count = Hash.new(0)
puts "count=#{count}"
# count={}
%w[a b b c c c].each do |char|
count[char] += 1
end
puts "count=#{count}"
# count={"a"=>1, "b"=>2, "c"=>3}
count = Hash.new
puts "count=#{count}"
%w[a b b c c c].each do |char|
count[char] += 1
# Fails: in `block in <main>': undefined method `+' for nil:NilClass (NoMethodError)
end
puts "count=#{count}"
另请参阅:
Hash.new
初始化哈希时,您可以设置默认值或默认过程(如果给定键不存在则返回的值)
关于理解这个魔法的问题,首先你需要知道 Ruby 哈希值有默认值。要访问默认值,您可以使用
Hash#default
方法
这个默认值默认:)是
nil
hash = {}
hash.default # => nil
hash[:key] # => nil
Hash#default=
设置默认值
hash = {}
hash.default = :some_value
hash[:key] # => :some_value
非常重要的注意事项:使用可变对象作为默认对象是危险的,因为这样的副作用:
hash = {}
hash.default = []
hash[:key] # => []
hash[:other_key] << :some_item # will mutate default value
hash[:key] # => [:some_value]
hash.default # => [:some_value]
hash # => {}
Hash#default_proc
和 Hash#default_proc=
方法
hash = {}
hash.default_proc # => nil
hash.default_proc = proc { [] }
hash[:key] # => []
hash[:other_key] << :some_item # will not mutate default value
hash[:other_key] # => [] # because there is no this key
hash[:other_key] = [:symbol]
hash[:other_key] << :some_item
hash[:other_key] # => [:symbol, :some_item]
hash[:key] # => [] # still empty array as default
设置
default
取消default_proc
,反之亦然
hash = {}
hash.default = :default
hash.default_proc = proc { :default_proc }
hash[:key] # => :default_proc
hash.default = :default
hash[:key] # => :default
hash.default_proc # => nil
回到
Hash.new
当您将参数传递给此方法时,您会初始化默认值
hash = Hash.new(0)
hash.default # => 0
hash.default_proc # => nil
当您将块传递给此方法时,您会初始化默认过程
hash = Hash.new { 0 }
hash.default # => nil
hash[:key] # => 0