如何在Ruby中初始化哈希中的数组

42
我试图初始化一个数组的哈希表,例如:
@my_hash = Hash.new(Array.new)

以便我能够:

@my_hash["hello"].push("in the street")
=> ["in the street"]
@my_hash["hello"].push("at home")
=> ["in the street", "at home"]
@my_hash["hello"]
=>["in the street", "at home"]
问题在于任何新的哈希键也会返回["in the street", "at home"]

The problem is that any new hash key also return ["in the street", "at home"]

@my_hash["bye"]
=> ["in the street", "at home"]
@my_hash["xxx"]
=> ["in the street", "at home"]

我做错了什么,初始化Hash of Arrays的正确方法是什么?


相关:https://dev59.com/9XVC5IYBdhLWcg3ww0Hr - tokland
3个回答

101
@my_hash = Hash.new(Array.new)

这将创建一个数组对象,并在每次未找到键时返回。由于您只会更改该数组,而不会创建新的数组,因此所有键都映射到同一个数组。

您需要做的是:

@my_hash = Hash.new {|h,k| h[k] = Array.new }

或者简单地说

@my_hash = Hash.new {|h,k| h[k] = [] }

通过 Hash.new 传递块和仅传递参数有两个不同之处:

  1. 每次未找到键时都会执行该块。因此,您每次都会得到一个新数组。在使用参数的版本中,参数在调用 new 之前被评估一次,并且每次都返回其结果。

  2. 通过执行h[k] =实际上将键插入哈希表中。如果您不这样做,仅访问@my_hash[some_key]将不会导致some_key插入哈希表中。


15
这里需要注意的一点是,即使仅仅是检查一个键是否存在,它也会被创建,这可能不是你想要的。因此,为了避免这种情况,有时我会正常地创建哈希表(只使用{}),然后在调用时进行数组创建,例如(@myhash [“hello”] ||= []).push(“在街上”) - glenn mcdonald

9

试试这个:

@my_hash = Hash.new { |h, k| h[k] = Array.new }

2

Hash.new的参数是用于新哈希键的默认值,因此当您传递一个引用时,该引用将用于新哈希键。当您调用...时,您正在更新该引用。

hash["key"].push "value"

在向哈希键中推送值之前,您需要将一个新的引用传递给它...

hash["key1"] = Array.new
hash["key1"].push "value1"
hash["key2"] = Array.new
hash["key2"].push "value2

你可以尝试将此内容封装成一个帮助方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接