Ruby中的哈希表是否允许有重复的键?

24

在Ruby中是否可以创建允许重复键的哈希表?

我正在使用Ruby 1.9.2。


1
简短回答是不行的,哈希必须有唯一的键。你为什么需要一个具有重复键的哈希? - Thiago Jackiw
1
你的意思是创建一个 Hash 类的实例,其中包含两个条目,每个条目都具有完全相同的键吗? - Ray Toal
你不想要这个,你需要牺牲性能才能允许这样做。 - user395760
1
@Thiago,那是一种中等回答。简短的回答是“不”。 :) - John La Rooy
也许阅读文档会有所帮助:“哈希是一种类似于字典的集合,包含唯一键和它们的值。” - the Tin Man
2个回答

48

在哈希表中实现重复键的两种方法:

h1 = {}
h1.compare_by_identity
h1["a"] = 1
h1["a"] = 2
p h1 # => {"a"=>1, "a"=>2}


h2 = {}
a1 = [1,2,3]
a2 = [1,2]
h2[a1] = 1
h2[a2] = 2
a2 << 3 
p h2 # => {[1, 2, 3]=>1, [1, 2, 3]=>2}

2
第一个例子正是我所寻找的。太棒了。 - B Seven
1
你好,Steenslag, 我使用了“compare_by_identity”来创建具有重复键的哈希表。但它没有起作用。请你帮帮我。 - Buddy
1
@Buddy,你使用什么作为键?整数和符号不行,因为只有一个1和一个:a - 重复是不可能的。compare_by_identity通过比较object_id来工作,普通哈希通过比较eql?方法的结果来比较。 - steenslag
2
奇怪...它在2.3.3上不起作用,但在2.4.2上却可以?! - steenslag
1
我们公司也遇到了类似的问题,我的老板想出了一个解决方案,使第一个示例在所有 Ruby 版本中都能正常工作。基本上,在某些 Ruby 版本(最新版?)中,当你写两次 h1['a'] 时,a 字符串对象会以不同的 ID 创建。但在其他版本中,每次写 h1['a'] 时,'a' 的 ID 都是相同的。解决方法是使用 h1['a'.clone] 来创建一个新的字符串对象。 - ivanibash
显示剩余3条评论

33
这样做有点违背散列表的初衷,不是吗? 如果你想让一个键指向多个元素,请使其指向一个数组:
h = Hash.new { |h,k| h[k] = [] }
h[:foo] << :bar
h #=> {:foo=>[:bar]}
h[:foo] << :baz
h #=> {:foo=>[:bar, :baz]}

实际上这取决于上下文。例如,在LDAP系统中,您可以拥有多个objectClass,并且是的,您可以像这样定义哈希值:attrs = { ..., displayName: user.short_name, objectClass: "organizationPerson", objectClass: "person", objectClass: "top", objectClass: "user", i } - Cyril Duchon-Doris
2
这可能是事实,但这并不意味着它就是一个关联数组(这就是 Ruby 哈希表的定义)。在计算机科学中,关联数组、映射、符号表或字典是一种抽象数据类型,由一组(键,值)对组成,以便于集合中每个可能的键只出现一次。重点强调。 - Michael Kohl
2
C++有multimaps和multisets,允许使用相同名称的多个键。从同一维基百科关于关联数组的页面中可以看到:“multimap通过允许将多个值与单个键相关联来概括关联数组。”因此,我不会说它是为了打败目的...但这只是一个不同的、有效的用例。 - Emile Vrijdags
当然,但是如果你看一下C++ multimap的模板,你会发现它比Ruby哈希表这样的简单关联数组更复杂。对于Ruby来说,有一些multimap的gems,例如https://github.com/doxavore/multimap。 - Michael Kohl

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