Ruby Hash.new怪异

时间:2012-10-11 11:31:18

标签: ruby hashmap

  

可能重复:
  Strange ruby behavior when using Hash.new([])

这很简单,因为我迷失了语言。

为什么会这样:

1.9.3-p194 :001 > h = Hash.new([])
 => {} 
1.9.3-p194 :002 > h[:key1] << "Ruby"
 => ["Ruby"] 
1.9.3-p194 :003 > h
 => {} 
1.9.3-p194 :004 > h.keys
 => [] 
1.9.3-p194 :005 > h[:key1]
 => ["Ruby"] 

5 个答案:

答案 0 :(得分:7)

当您创建这样的哈希时:

h = Hash.new([])       

这意味着,每当使用尚未定义的密钥访问哈希时,它将返回:

[]

现在你做的时候:

h[:key1] << "Ruby"

h[:key1]已返回[],其中"Ruby"被推送,导致["Ruby"]作为输出,因为这是最后返回的对象。当使用未定义的键访问'h'时,它也被设置为返回的默认值。 因此,当你这样做时:

h[:key1] or h[:key2] or h[:whatever]

你会得到

"Ruby"

作为输出。 希望这会有所帮助。

答案 1 :(得分:2)

此构造Hash.new([])返回默认值,但此值不是hash的初始化值。假设默认值是哈希的一部分,您正尝试使用哈希。

你需要的是在某些键上初始化哈希的构造:

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

hash[:key1] << "Ruby"

hash #=> {:key1=>["Ruby"]}

答案 2 :(得分:2)

查看Hash.new的文档

new → new_hash
new(obj) → new_hash
new {|hash, key| block } → new_hash

如果随后通过与散列条目不对应的键访问此散列,则返回的值取决于用于创建散列的新样式。

  1. 在第一种形式中,访问返回nil。
  2. 如果指定了obj,则此单个对象将用于所有默认值。
  3. 如果指定了一个块,它将使用哈希对象和键调用,并应返回默认值。如果需要,该块负责将值存储在哈希值中。

  4. irb(main):015:0> h[:abc] # ["Ruby"]
    

    因此,如果找不到密钥,则["Ruby"]将作为默认值返回,而不是nil。

答案 3 :(得分:2)

您实际上没有使用h[:keys] << "Ruby"设置值。您只需为未找到的键的返回默认数组添加一个值。所以没有创建密钥。

如果你写这个,那就没关系了:

h = Hash.new([])
h[:keys1] = []
h[:keys1] << "Ruby"

答案 4 :(得分:1)

我不得不承认,当我读到你的问题时,这也让我失望了。我看了docs,但很明显。

  

如果指定了 obj ,则此单个对象将用于所有默认值

所以你真正在做的是修改这个用于默认值的单个数组对象,而不必分配给键!

检查出来:

h = Hash.new([])

h[:x] << 'x'
# => ['x']

h
# => {}

h[:y]
# => ['x']  # CRAZY TIMES

所以你需要以某种方式做作业 - h[:x] += ['x']可能是你要走的路。