使用具有默认值的哈希
Working with Hashes that have a default value
正在学习使用 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
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}"
另请参见:
扩展@jeremy-ramos 的回答和@mu-is-too-short 的评论。
在这种方式下,默认哈希值有两个常见问题。
1。意外共享引用。
Ruby 使用您传入的内存中的 完全相同的 对象作为每个丢失的键的默认值。
对于不可变对象(如0
),没有问题。但是你可能想写这样的代码:
hash = Hash.new([])
hash[key] << value
或
hash = Hash.new({})
hash[key][second_key] = value
这不会达到您的预期。而不是 hash[unknown_key]
return 创建一个新的空数组或散列,它将 return 每个键的完全相同的 array/hash 对象。
这样做:
hash = Hash.new([])
hash[key1] << value1
hash[key2] << value2
生成一个散列,其中 key1
和 key2
都指向包含 [value1, value2]
的同一个数组对象
见
解决方案
要解决这个问题,您可以创建一个带有默认块参数的散列(每当访问丢失的键时调用它,并允许您为丢失的键分配一个值)
hash = Hash.new{|h, key| h[key] = [] }
2。使用默认值分配丢失的键
当您访问默认值为 return 的缺失键时,您可能希望散列现在包含该键且值为 returned。它不是。 Ruby 不修改散列,它只是 return 的默认值。所以,例如:
hash = Hash.new(0) #$> {}
hash.keys.empty? #$> true
hash[:foo] #$> 0
hash[:foo] == 0 #$> true
hash #$> {}
hash.keys.empty? #$> true
解决方案
这种混淆也可以使用块方法解决,其中可以显式设置键值。
TL;DR 当您使用 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
and 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
正在学习使用 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
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}"
另请参见:
扩展@jeremy-ramos 的回答和@mu-is-too-short 的评论。
在这种方式下,默认哈希值有两个常见问题。
1。意外共享引用。
Ruby 使用您传入的内存中的 完全相同的 对象作为每个丢失的键的默认值。
对于不可变对象(如0
),没有问题。但是你可能想写这样的代码:
hash = Hash.new([])
hash[key] << value
或
hash = Hash.new({})
hash[key][second_key] = value
这不会达到您的预期。而不是 hash[unknown_key]
return 创建一个新的空数组或散列,它将 return 每个键的完全相同的 array/hash 对象。
这样做:
hash = Hash.new([])
hash[key1] << value1
hash[key2] << value2
生成一个散列,其中 key1
和 key2
都指向包含 [value1, value2]
见
解决方案
要解决这个问题,您可以创建一个带有默认块参数的散列(每当访问丢失的键时调用它,并允许您为丢失的键分配一个值)
hash = Hash.new{|h, key| h[key] = [] }
2。使用默认值分配丢失的键
当您访问默认值为 return 的缺失键时,您可能希望散列现在包含该键且值为 returned。它不是。 Ruby 不修改散列,它只是 return 的默认值。所以,例如:
hash = Hash.new(0) #$> {}
hash.keys.empty? #$> true
hash[:foo] #$> 0
hash[:foo] == 0 #$> true
hash #$> {}
hash.keys.empty? #$> true
解决方案
这种混淆也可以使用块方法解决,其中可以显式设置键值。
TL;DR 当您使用 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
and 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