2015-06-08 106 views
0

尋找一種優雅的方式合併散列值的兩個陣列以特殊的方式的兩個數組:結合哈希

new_data = [{"name" => "a"}, {"name" => "b"}, {"name" => "c"}] 
old_data = [{"name" => "a", "data" => "extra1"}, {"name" => "d", "data2" => "extra"}] 
result = [{"name" => "a", "data" => "extra1"}, {"name" => "b"}, {"name" => "c"}] 

結果必須擁有所有的new_data名稱哈希有如果old_data只是額外的數據名稱鍵匹配。

我第一次嘗試是這樣,但它創造了一個額外的哈希:

def combine(new_data, old_data) 
    int = [] 
    new_data.each do |s| 
    old_data.each do |e| 
     (int << (s.merge e)) if e["name"] == s["name"] 
    end 
    int << s 
    end 
    int 
end 

# => [{"name"=>"a", "data"=>"extra1"}, {"name"=>"a"}, {"name"=>"b"}, {"name"=>"c"}] 

回答

5

一個單行,但可能不是太大的表演在大集。

new_data.map{ |e| e.merge(old_data.detect{ |e2| e2['name'] == e['name'] } || {}) } 
+0

有趣,但你做了很多工作,爲new_data'的'每個元素。我認爲最好先爲'old_data'構造一個查找哈希(就像@tadman爲'old_data'完成的那樣。 –

+0

謝謝,我喜歡! – andreofthecape

1

這是一個有點棘手,但你可以從new_data轉換成查找散解決它,然後遍歷old_data到合併內容:

new_data = [{"name" => "a"}, {"name" => "b"}, {"name" => "c"}] 
old_data = [{"name" => "a", "data" => "extra1"}, {"name" => "d", "data2" => "extra"}] 

# Transform into a lookup table using "name" as a key 
lookup = Hash[new_data.collect { |v| [ v['name'], v ] }] 

old_data.each do |data| 
    # Match based on "name" 
    found = lookup[data['name']] 

    next unless (found) 

    # If found, swap out the element with a merged version 
    # so the original is preserved as-is, not mangled. 
    lookup[data['name']] = found.merge(data) 
end 

lookup.values 
# => [{"name"=>"a", "data"=>"extra1"}, {"name"=>"b"}, {"name"=>"c"}] 
0

假設

我假定:

    在兩個 new_data一個 old_data"name"的值是唯一的
  • ;
  • new_data是包含一個鍵值對的散列數組;和
  • old_data是包含至少兩個鍵值對的散列數組。

代碼

def extract_elements(new_data, old_data) 
    (new_data+old_data).group_by { |h| h["name"] }. 
         values. 
         select { |a| a.size > 1 || a.first.size == 1 }. 
         map(&:last) 
end 

new_data = [{"name" => "a"}, {"name" => "b"}, {"name" => "c"}] 
old_data = [{"name" => "a", "data" => "extra1"}, 
      {"name" => "d", "data2" => "extra"}] 
extract_elements(new_data, old_data) 
    #=> [{"name"=>"a", "data"=>"extra1"}, {"name"=>"b"}, {"name"=>"c"}] 

說明

對於上面的例子:

a = (new_data+old_data) 
    #=> [{"name"=>"a"}, {"name"=>"b"}, {"name"=>"c"}, 
    # {"name"=>"a", "data"=>"extra1"}, {"name"=>"d", "data2"=>"extra"}] 
b = a.group_by { |h| h["name"] } 
    #=> {"a"=>[{"name"=>"a"}, {"name"=>"a", "data"=>"extra1"}], 
    # "b"=>[{"name"=>"b"}], 
    # "c"=>[{"name"=>"c"}], 
    # "d"=>[{"name"=>"d", "data2"=>"extra"}]} 
c = b.values 
    #=> [[{"name"=>"a"}, {"name"=>"a", "data"=>"extra1"}], 
    # [{"name"=>"b"}], 
    # [{"name"=>"c"}], 
    # [{"name"=>"d", "data2"=>"extra"}]] 
d = c.select { |a| a.size > 1 || a.first.size == 1 } 
    #=> [[{"name"=>"a"}, {"name"=>"a", "data"=>"extra1"}], 
    # [{"name"=>"b"}], 
    # [{"name"=>"c"}]] 
e = d.map(&:last) 
    #=> [{"name"=>"a", "data"=>"extra1"}, 
    # {"name"=>"b"}, 
    # {"name"=>"c"}] 

限制性條款

這需要Ruby V1.9 +,因爲它需要被保持的哈希b鑰匙插入順序。對於早期版本,替換:

map(&:last) 

有:

map { |h| h.max_by(&:size) }