2

可能重复:
使用 Hash.new([]) 时出现奇怪的 ruby​​ 行为

这是一个简单的,因为我失去了言语。

为什么会这样:

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"] 
4

5 回答 5

8

当您创建这样的哈希时:

h = Hash.new([])       

这意味着,每当使用尚未定义的键访问哈希时,它都会返回:

[]

现在当你这样做时:

h[:key1] << "Ruby"

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

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

你会得到

"Ruby"

作为输出。希望这可以帮助。

于 2012-10-11T11:48:14.310 回答
4

查看 Hash.new 的文档

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

如果此哈希随后被不对应于哈希条目的键访问,则返回的值取决于用于创建哈希的 new 的样式。

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

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

["Ruby"]如果未找到键,则返回默认值而不是 nil 。

于 2012-10-11T11:39:11.167 回答
2

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

您需要的是在某个键处初始化散列的构造:

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

hash[:key1] << "Ruby"

hash #=> {:key1=>["Ruby"]}
于 2012-10-11T11:37:03.127 回答
2

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

如果你写这个,那就没问题了:

h = Hash.new([])
h[:keys1] = []
h[:keys1] << "Ruby"
于 2012-10-11T11:40:08.347 回答
1

我不得不承认,当我阅读您的问题时,这也让我感到困惑。我看了一下文档,但它变得很清楚。

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

因此,您实际上所做的是修改这个用于默认值的单个数组对象,而无需分配给键!

看看这个:

h = Hash.new([])

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

h
# => {}

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

因此,您需要以某种方式进行分配-h[:x] += ['x']可能是要走的路。

于 2012-10-11T11:43:47.710 回答