我以为我理解默认方法对哈希的作用...
如果密钥不存在,请为其提供默认值:
irb(main):001:0> a = {}
=> {}
irb(main):002:0> a.default = 4
=> 4
irb(main):003:0> a[8]
=> 4
irb(main):004:0> a[9] += 1
=> 5
irb(main):005:0> a
=> {9=>5}
Run Code Online (Sandbox Code Playgroud)
都好.
但是,如果我设置的默认是一个空列表,或空哈希,我不知道这是在行为都 ....
irb(main):001:0> a = {}
=> {}
irb(main):002:0> a.default = []
=> []
irb(main):003:0> a[8] << 9
=> [9] # great!
irb(main):004:0> a
=> {} # ?! would have expected {8=>[9]}
irb(main):005:0> a[8]
=> [9] # awesome!
irb(main):006:0> a[9]
=> [9] # unawesome! shouldn't this be [] ??
Run Code Online (Sandbox Code Playgroud)
我希望/期待相同的行为,好像我使用了|| =运算符...
irb(main):001:0> a = {}
=> {}
irb(main):002:0> a[8] ||= []
=> []
irb(main):003:0> a[8] << 9
=> [9]
irb(main):004:0> a
=> {8=>[9]}
irb(main):005:0> a[9]
=> nil
Run Code Online (Sandbox Code Playgroud)
谁能解释一下发生了什么?
gle*_*ald 52
这是一个非常有用的习语:
(myhash[key] ||= []) << value
Run Code Online (Sandbox Code Playgroud)
它甚至可以嵌套:
((myhash[key1] ||= {})[key2] ||= []) << value
Run Code Online (Sandbox Code Playgroud)
另一种方法是:
myhash = Hash.new {|hash,key| hash[key] = []}
Run Code Online (Sandbox Code Playgroud)
但这有一个重要的副作用,询问一个键是否会创建它,这会产生has_key?相当没用,所以我避免这种方法.
Aar*_*nni 49
Hash.default
用于设置查询不存在的键时返回的默认值.不会为您创建集合中的条目,只是因为查询它.
此外,您设置的值default
是对象的实例(在您的情况下为数组),因此返回时,可以对其进行操作.
a = {}
a.default = [] # set default to a new empty Array
a[8] << 9 # a[8] doesn't exist, so the Array instance is returned, and 9 appended to it
a.default # => [9]
a[9] # a[9] doesn't exist, so default is returned
Run Code Online (Sandbox Code Playgroud)
Tur*_*urp 33
我认为这是你正在寻找的行为.这将自动将哈希中的任何新键初始化为数组:
irb(main):001:0> h = Hash.new{|h, k| h[k] = []}
=> {}
irb(main):002:0> h[1] << "ABC"
=> ["ABC"]
irb(main):003:0> h[3]
=> []
irb(main):004:0> h
=> {1=>["ABC"], 3=>[]}
Run Code Online (Sandbox Code Playgroud)
格伦麦克唐纳说:
"另一种方法是:
myhash = Hash.new {| hash,key | hash [key] = []}
但这有一个重要的副作用,询问一个键是否会创建它,这会产生has_key?相当没用,所以我避免使用这种方法."
事实上似乎并非如此.
irb(main):004:0> a = Hash.new {|hash,key| hash[key] = []}
=> {}
irb(main):005:0> a.has_key?(:key)
=> false
irb(main):006:0> a[:key]
=> []
irb(main):007:0> a.has_key?(:key)
=> true
Run Code Online (Sandbox Code Playgroud)
正如我所料,访问密钥将创建它.仅仅问has_key?才不是.
小智 9
如果你真的想要一个无休止的深度哈希:
endless = Hash.new { |h, k| h[k] = Hash.new(&h.default_proc) }
endless["deep"]["in"]["here"] = "hello"
Run Code Online (Sandbox Code Playgroud)
当然,正如格伦指出的那样,如果你这样做,那么has_key?失去意义,因为它总会回归真实.对于这一个来说,这是一个jbarnette.
irb(main):002:0> a.default = []
=> []
irb(main):003:0> a[8] << 9
=> [9] # great!
Run Code Online (Sandbox Code Playgroud)
使用此语句,您已修改了默认值; 你还没有创建一个新的数组并添加了"9".此时,如果你这样做了,那就完全相同了:
irb(main):002:0> a.default = [9]
=> [9]
Run Code Online (Sandbox Code Playgroud)
因此,你现在得到这个并不奇怪:
irb(main):006:0> a[9]
=> [9] # unawesome! shouldn't this be [] ??
Run Code Online (Sandbox Code Playgroud)
此外,'<<'将'9'添加到数组中; 它没有将它添加到哈希,这解释了这个:
irb(main):004:0> a
=> {} # ?! would have expected {8=>[9]}
Run Code Online (Sandbox Code Playgroud)
您可能想要在程序中执行以下操作,而不是使用.default:
# Time to add a new entry to the hash table; this might be
# the first entry for this key..
myhash[key] ||= []
myhash[key] << value
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
14610 次 |
最近记录: |