使用整数作为哈希键的用途

74

在 Ruby 哈希表中使用整数作为键是否合适?

文档中的每个示例都展示了使用字符串或符号作为键,但从未展示过使用整数。

在内部,整数是否会以某种方式转换为字符串?我看到了关于这个问题的一些相互矛盾的信息。

换句话说,使用整数键对哈希表是否有任何显著的不利影响?


2
你试过了吗?在控制台上,你可以输入IRB并获得一个Ruby控制台..非常有用来尝试这种类型的事情...关于这个话题,你应该能够很好地使用整数。 - Deleteman
1
“除了索引是通过任意对象类型的任意键进行的”(http://www.ruby-doc.org/core/Hash.html)。在Ruby中,整数是对象,哈希也是对象,因此您可以使用哈希作为键。 - mu is too short
4个回答

83

其他人看这里的答案可能会发现,如果在Ruby哈希表{symbol: value}中使用整数作为符号键时会发生异常。

hash = {1: 'one'} # will not work  
hash = {1 => 'one'} # will work

请求解释:

第一个示例失败的最简单的答案可能是to_sym不是针对Fixnum整数实现的方法。

更深入地解释一下为什么会这样,使用符号的主要好处之一是,两个符号实际上是“相同的对象”。或者至少它们共享相同的对象ID。

:foo.object_id == :foo.object_id
=> true

相同的字符串不共享相同的对象,因此不共享相同的对象id。

"foo".object_id == "foo".object_id
=> false

像符号一样,相同的Fixnum整数将具有相同的对象ID。因此,您实际上不需要将它们转换为符号。

one = 1
=> 1
uno = 1
=> 1
one.object_id
=> 3
one.object_id == uno.object_id
=> true

这只是“新”Ruby哈希语法的一种特殊性,该语法使用符号作为键,并在Ruby 1.9中引入。这不是Ruby哈希实现中的限制。仅当您想要将符号用作键时,例如 {this: 'one',that: 'two'}才适用此语法。它只是哈希类支持的子集。 - Tilo
1
Ruby是我曾经使用过的最不可靠的语言。 - duhaime

73
当然你可以使用整数作为键...
h = {1 => 'one', 2 => 'two', 3 => 'three'}

(1..3).each do |i|
  puts h[i]
end
 

=>

one
two
there

irb是你的朋友!试试看吧...


实际上,你可以使用任何 Ruby 对象作为键(或值)。 我们通常不会考虑使用哈希表,但它可能非常有用。
编辑: 如Óscar López指出,这个对象只需要回应.hash就可以作为 Ruby 哈希表中的键。

12
关于具有数字键的哈希字面量,我发现有趣的一件事是你不能使用语法{1:'one', 2:'two'}。我猜这种语法假定每个键都是符号,而整数不是。 - BlueMonkMN
这是 Ruby 1.9 哈希语法的一个特殊之处。这不是哈希类的一般限制。 - Tilo

9

将对象用作哈希键的唯一要求是它必须响应消息哈希并返回哈希值,并且给定键的哈希值不能更改。例如,如果您调用此函数:

1.hash()

您可以看到数字1实际上是对哈希消息的响应。

我认为在1.8版本中是这样的。但我不确定在1.9版本中是否仍然如此。我的意思是,在1.9版本中,你可以免费获得一个哈希值。 - Candide
没错,我并不是说你必须在要用作键的对象上显式调用hash()方法 - 重要的是该对象实现了hash()方法(或者在面向对象的范畴中,可以“响应hash消息”)。 - Óscar López
6
它还必须响应 eql? - Jörg W Mittag

3
已经有关于“是否可能”的答案了。
为什么没有整数作为哈希键的示例呢?
哈希键通常具有含义。它可以是属性名及其值(例如,:color => 'red'...)。
当您把一个整数作为键时,您所表达的意思可能是“第一、第二……”(1)。但是,这样您就不使用哈希表了,而是要使用数组来存储您的值。
(1)反例可能是数据库中的外键。

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