2017-02-22 36 views
1

很多時候我需要散列一對值。通常,我只是在num1和num2之間生成一個範圍,並將其作爲一個鍵進行散列,但這很慢,因爲這兩個數字之間的距離可能非常大。使用一對值作爲密鑰

如何才能將一對值散列到表中?例如,假設我正在遍歷一個數組,並且希望將每個可能的一對值散列到散列表中,其中鍵是num對,並且值是它們的總和。什麼是有效的方法來做到這一點?我也想過把一個數組散列爲關鍵字,但這不起作用。

另外,如何將其擴展到3,4或5個數字?

編輯: 我指的散列表中的O(1)查找散列。

+0

你可以散列一個字符串''num1:num2''嗎? – Dbz

+0

@Dbz我不確定這是否有效 - 在將它們散列之前將數字轉換爲字符串。但是,如果這是最好的方式,那麼我肯定這是正確的。 – Sunny

+0

是否都是正值?他們是整數嗎? – eiko

回答

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 

正如你看到的,我需要一些陣列,克隆它們,分別修改它們;在此之後,我們確信ee2是不同的陣列(即不同的對象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(其他)→真或假

返回是否真實的自我等是同一個對象,或具有相同內容兩個數組(?根據Object#eql?)。

散列→整數

計算此數組的散列碼。

相同內容的兩個數組將具有相同的散列碼(並且將使用eql?進行比較)。

強調我的。

+0

這似乎與我的答案是一樣的:)更多的解釋如何'哈希'工程 – Dbz

1

如果您使用的是rangearray,那麼您也可以撥打hash並使用它。

(num1..num2).hash [num1, num2].hash

將返回,你可以作爲哈希使用的密鑰。我不知道這是否有效。它確實在range documentationarray 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 }

+0

'哈希'返回的值不保證是唯一的,以避免衝突。他們只是應該是獨一無二的。 – tadman

+0

@tadman你有這個來源嗎? – Dbz

+2

這就是散列函數的*定義:它將一個大的(r)(可能是無限的)輸入空間映射到一個小的(er)有限的輸出空間。 Pigeonhole原則保證*必須*有碰撞。 –

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