我经常需要散列一对值。通常,我只是生成num1和num2之间的范围,并将其作为关键字哈希,但这很慢,因为这两个数字之间的距离可能非常大。
如何将一对值散列到表中呢?例如,假设我在遍历一个数组并希望将每一个可能的值对散列到一个哈希表中,其中键是一对nums,值是它们的总和。这是一种有效的方法吗?我也想过将一个数组哈希作为关键,但这并不起作用。
另外,如何将此扩展到3,4或5个数字?
编辑: 我指的是散列表中的O(1)查找散列。
答案 0 :(得分:1)
如果您使用的是range
或array
,那么您也可以在其上调用hash
并使用它。
(num1..num2).hash
[num1, num2].hash
这将返回一个可用作哈希的键。我不知道这是否有效。它确实显示了range documentation和array documentation
上的源代码我要做的另一种方法是将数字转换为字符串。如果您担心哈希冲突,这是更好的解决方案。
'num1:num2'
我将解决你问题的红宝石式方法是:
number_array.combination(2).each { |arr| my_hash[arr.hash] = arr }
number_array.combination(2).each { |arr| my_hash[arr.join(":")] = arr }
答案 1 :(得分:1)
你可以简单地在数组上哈希......
让我展示一个小实验:
array = [ [1,2], [3,4], ["a", "b"], ["c", 5] ]
hash = {}
array.each do |e|
e2 = e.clone
e << "dummy"
e2 << "dummy"
hash[e] = (hash[e] || 0) + 1
hash[e2] = (hash[e2] || 0) + 1
puts "e == e2: #{(e==e2).inspect}, e.id = #{e.object_id}, e.hash = #{e.hash}, e2.id = #{e2.object_id}, e2.hash = #{e2.hash}"
end
puts hash.inspect
如你所见,我拿了几个数组,克隆它们,分别修改它们;在此之后,我们确信e
和e2
是不同的数组(即不同的对象ID);但它们包含相同的元素。在此之后,两个不同的数组用作散列键;由于它们具有相同的内容,因此被混合在一起。
e == e2: true, e.id = 19797864, e.hash = -769884714, e2.id = 19797756, e2.hash = -769884714
e == e2: true, e.id = 19797852, e.hash = -642596098, e2.id = 19797588, e2.hash = -642596098
e == e2: true, e.id = 19797816, e.hash = 104945655, e2.id = 19797468, e2.hash = 104945655
e == e2: true, e.id = 19797792, e.hash = -804444135, e2.id = 19797348, e2.hash = -804444135
{[1, 2, "dummy"]=>2, [3, 4, "dummy"]=>2, ["a", "b", "dummy"]=>2, ["c", 5, "dummy"]=>2}
如您所见,您不仅可以将数组用作键,还可以将它们识别为“相同”(而不是它也可能是一些奇怪的对象标识)。
显然这只适用于某一点。对于散列,数组的内容必须递归地定义良好。也就是说,你可以在那里使用像字符串,数字,其他数组,甚至nil
这样的理智的东西。
来自http://ruby-doc.org/core-2.4.0/Hash.html:
当两个对象的哈希值相同且两个对象是eql时,它们引用相同的哈希键?彼此。
来自http://ruby-doc.org/core-2.4.0/Array.html#method-i-eql-3F:
eql?(其他)→真或假
如果self和other是同一个对象,或者是具有相同内容的数组(根据Object#eql?),则返回true。
哈希→整数
计算此数组的哈希码。
具有相同内容的两个数组将具有相同的哈希码(并将使用eql进行比较?)。
强调我的。
答案 2 :(得分:0)
哈希表,其中键是一对nums,值是它们的总和:
h = {}
[1,4,6,8].combination(2){|ar| h[ar] = ar.sum}
p h #=>{[1, 4]=>5, [1, 6]=>7, [1, 8]=>9, [4, 6]=>10, [4, 8]=>12, [6, 8]=>14}
请注意,使用数组作为哈希键完全没问题。要将其扩展为3,4或5个数字,请使用combination(3) #or 4 or 5
。