Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 产生默认数组的哈希中的哈希_Ruby_Hash - Fatal编程技术网

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]}}