Ruby 产生默认数组的哈希中的哈希
假设我有:Ruby 产生默认数组的哈希中的哈希,ruby,hash,Ruby,Hash,假设我有: a = Hash.new a['google.com'][:traffic] << 50 a['google.com'][:traffic] << 20 a['google.com'][:popular] << 1 a['google.com'][:popular] << 2 3a['yahoo.com'][:anythinghere] << 3 到目前为止,我已经尝试过这种方法,希望它能产生这样的结果: a= Hash.
a = Hash.new
a['google.com'][:traffic] << 50
a['google.com'][:traffic] << 20
a['google.com'][:popular] << 1
a['google.com'][:popular] << 2
3a['yahoo.com'][:anythinghere] << 3
到目前为止,我已经尝试过这种方法,希望它能产生这样的结果:
a= Hash.new(Hash.new(Array.new))
例如,a['google.com']
将生成一个新的哈希,而a['google.com'][:anythinghere]
将生成一个新数组。但是,当我尝试执行上述插入时,a
为空?不知道发生了什么,我很确定我错过了一些基本的东西。看一看:
a = stats = Hash.new(Hash.new(Array.new))
a['google.com'][:traffic] << 5
a['google.com'][:traffic] << 6
p a['google.com'][:traffic] #=> [5,6]
p a['google.com'] #=> empty hash???
p a #=> empty hash???
a=stats=Hash.new(Hash.new(Array.new))
一个['google.com'][:traffic]空散列???
p a#=>空哈希???
您可以使用以下行:Hash.new{h,k{h[k]=Hash.new{h2,k2}h2[k2]=[]}
a = Hash.new { |h, k| h[k] = Hash.new { |h2, k2| h2[k2] = [] } }
a['google.com'][:traffic] << 50
a['google.com'][:traffic] << 20
a['google.com'][:popular] << 1
a['google.com'][:popular] << 2
a['yahoo.com'][:anythinghere] << 3
a
# => {"google.com"=>{:traffic=>[50, 20], :popular=>[1, 2]}, "yahoo.com"=>{:anythinghere=>[3]}}
之所以会出现这种意外行为,是因为当您将默认值作为参数传递给散列到
new
时,一个对象是所有键的默认值。例如:
s = "but"
a = Hash.new(s)
a['x'].concat 't'
puts a['y']
# butt
puts s
# butt
这是有意义的,因为Ruby使用指针传递对象,所以每当您获得默认值时,它实际上是指向您传递的原始对象的指针
要解决此问题,可以在块中设置默认值。这样,哈希必须在每次需要默认值时重新计算块:
a = Hash.new { "but" }
a['x'].concat 't'
puts a['x']
# but
puts a.size
# 0
下一个问题是,当Ruby获得默认值时,它不会将其分配给任何键。这就是为什么在上一个示例中访问密钥后,哈希的大小仍然为0。这个问题也可以解决,因为Ruby为默认值块提供散列本身和缺少的键,所以我们可以在那里进行赋值:
a = Hash.new { |hash, key| hash[key] = "but" }
a['x'].concat 't'
puts a['x']
# butt
puts a['y']
# but
puts a.size
# 2
另一种方式:
代码
def hashify(arr)
arr.each_with_object({}) do |e,h|
*hash_keys, array_key, value = e
g = hash_keys.reduce(h) { |g,k| g[k] ||= {} }
(g[array_key] ||= []) << value
end
end
我喜欢答案,然后你可以自己去推导答案。谢谢
a = Hash.new { |hash, key| hash[key] = "but" }
a['x'].concat 't'
puts a['x']
# butt
puts a['y']
# but
puts a.size
# 2
def hashify(arr)
arr.each_with_object({}) do |e,h|
*hash_keys, array_key, value = e
g = hash_keys.reduce(h) { |g,k| g[k] ||= {} }
(g[array_key] ||= []) << value
end
end
a = [['google.com', :traffic, 50],
['google.com', :traffic, 20],
['google.com', :popular, 1],
['google.com', :popular, 2],
['yahoo.com', :anythinghere, 3],
['yahoo.com', :anythinghere, 4]]
hashify(a)
#=> {"google.com"=>{:traffic=>[50, 20],
# :popular=>[1, 2]},
# "yahoo.com"=>{:anythinghere=>[3, 4]}}
a = [['google.com', :traffic, 50],
['google.com', :traffic1, :cat, :dog, 20],
['google.com', :traffic1, :cat, :dog, 30],
['google.com', :popular, 1],
['google.com', :popular, 2],
['yahoo.com', :anythinghere, 3],
['yahoo.com', :anythinghere, 4]]
hashify(a)
#=> {"google.com"=>{:traffic=>[50], :traffic1=>{:cat=>{:dog=>[20, 30]}},
# :popular=>[1, 2]},
# "yahoo.com"=>{:anythinghere=>[3, 4]}}