2015-10-08 46 views
0

我有兩個散列:紅寶石 - 合併兩個散列,並保持有序的按鍵

a = {"0"=>"name", "1"=>"email"} 
b = {"0"=>"source", "1"=>"info", "2"=>"extra", "3"=>"name"} 

我想通過以下操作創建一個哈希:

1)當兩個散列包含相同的值,保值原始散列值和第二個散列值的丟棄值。

2)當第二個散列的值不在第一個散列時,只需添加到新散列的末尾,確保該鍵是有序的。

這個結果:

{"0"=>"name", "1"=>"email", "2"=>"source", "3"=>"info", "4"=>"extra"} 

我做了這個醜陋的方式:

l1 = a.keys.length 
l2 = b.keys.length 
max = l1 > l2 ? l1 : l2 
counter = l1 
result = {} 
max.times do |i| 
    unless a.values.include? b[i.to_s] 
    result[counter.to_s] = b[i.to_s] 
    counter += 1 
    end 
end 
a.merge!(result) 

是否有一個內置的紅寶石方法或工具,它可以實現一個更清潔的方式完成相同的任務?

+5

這是一個非常古怪的數據結構。爲什麼不使用數組呢?字符串索引看起來完全是任意的,並且將會是一種難以分類的痛苦。例如,如果它們是字符串,則爲「0,1,10,2」。 – tadman

+0

有沒有這樣的事情,有序的哈希。 – Mircea

+3

@Mircea,我相信Ruby 1.9添加了有序哈希,它保留了插入順序。 –

回答

2
(a.values + b.values).uniq.map.with_index{|v, i| [i.to_s, v]}.to_h 
# => {"0"=>"name", "1"=>"email", "2"=>"source", "3"=>"info", "4"=>"extra"} 
+2

代碼非常密集的塊。可以變成一個通用函數,它使用N個參數,如:def crunch(* hashes)和hashes.collect(&:values).inject(:+).uniq'來計算重疊。 – tadman

1

首先創建一個包含散列值的數組。這可以通過concat方法來完成。現在我們有一個數組,我們可以調用uniq方法來檢索所有唯一值。這也保留了順序。

a = { "0" => "name", "1" => "email" } 
b = { "0" => "source", "1" => "info", "2" => "extra", "3" => "name" } 
values = a.values.concat(b.values).uniq 

在Ruby中生成哈希的快捷方式是這個技巧。

Hash[[*0..values.length-1].zip(values)] 

輸出:

{0=>"name", 1=>"email", 2=>"source", 3=>"info", 4=>"extra"} 
1
a = {"0"=>"name", "1"=>"email"} 
b = {"0"=>"source", "1"=>"info", "2"=>"extra", "3"=>"name"} 

key = (a.size-1).to_s 
    #=> "1" 
b.each_value.with_object(a) { |v,h| (h[key.next!] = v) unless h.value?(v) } 
    #=> {"0"=>"name", "1"=>"email", "2"=>"source", "3"=>"info", "4"=>"extra"}