2016-10-04 16 views
2

2つの配列があり、それぞれ異なるハッシュで構成されています。ruby​​異なる配列のハッシュ値を比較する

new_array1 = [ 
        {:index=>4, :column=>0, :ID=>"ABC"}, 
        {:index=>4, :column=>1, :ID=>"XYZ"}, 
        {:index=>4, :column=>2, :ID=>"BCD-1547"} 
       ] 


new_array2 = [ 
        {:index=>4, :column=>0, :ID=>"ABC"}, 
        {:index=>4, :column=>1, :ID=>"IJK"}, 
        {:index=>4, :column=>2, :ID=>"BCD-1547"} 
       ] 

私は:index:column値が同じである場合にのみ、new_array2の値対new_array1:IDキーの値を比較したいです。

ie) 
if (new_array1[0][:index] == new_array2[0][:index]) and (new_array1[0][:column] == new_array2[0][:column]) 
    if(new_array1[0][:ID] == new_array2[0][:ID]) 
     # do something 
    end 
end 

両方の配列のすべてのハッシュをループして一致する方法がありますか?それとも、ルビーでこれを行うよりエレガントな方法でしょうか?

答えて

2

これは、一致ハッシュの配列を返します。

res = new_array1.inject([]) { |memo, hash| memo << hash if new_array2.any? { |hash2| hash[:ID] == hash2[:ID] && hash[:index] == hash2[:index] && hash[:column] == hash2[:column] }; memo } 
# => [{:index=>4, :column=>0, :ID=>"ABC"}, {:index=>4, :column=>1, :ID=>"XYZ"}, {:index=>4, :column=>2, :ID=>"BCD-1547"}] 

res.each do |hash| 
    # do something 
end 

new_array1内のアイテムは、それが含まれるnew_array2の任意の項目と同じindexcolumnIDキーを持っている場合。

これらは平等比較すること==を使用して、ハッシュの唯一の鍵である場合にもsimpifyできます。エイリアスともreduceとして知られている

res = new_array1.inject([]) { |memo, hash| memo << hash if new_array2.any? { |hash2| hash == hash2 }; memo } 

inject方法は、コレクションを取り、新しい価値を創造しますそれから、injectに与えられたブロックが呼び出されるたびに、コレクションの次の要素と前のブロックの戻り値が与えられます(最初にブロックが呼び出されたときには、injectに渡されたシード値が与えられます)。これにより、再帰と同様の値を構築できます。

はここinjectのいくつかの例があります:Need a simple explanation of the inject method

any?メソッドは、指定されたブロックは、指定されたコレクションの要素のいずれかのためにtrueを返すとすぐにtrueを返します。ブロックがtrueを返さない場合、any?はfalseを返します。だから、:

[0,0,0,1,0].any? { |num| num == 1 } # => true 
[0,0,0,0,0].any? { |num| num == 1 } # => false 
+0

1.「each_with_object」と2を使用することを検討してください。これがどのように「#何か」に役立つのですか? – mudasobwa

+0

@ mudasobwa彼らは何かを行うために 'res'を繰り返すことができます、私は答えを更新します。 – Kris

+0

これは私が探しているものです、ありがとう!! あなたは 'inject([])'と 'any?' doの説明ができます – danynl

0
[new_array1, new_array2].map do |a| 
    a.group_by { |e| [e[:index], e[:column]] } 
end.reduce do |f, l| 
    f.merge(l) { |_, f, l| [f.first[:ID], l.first[:ID]] } 
end 
# => { 
#  [ 4, 0 ] => [ 
#   [0] "ABC", 
#   [1] "ABC" 
#  ], 
#  [ 4, 1 ] => [ 
#   [0] "XYZ", 
#   [1] "IJK" 
#  ], 
#  [ 4, 2 ] => [ 
#   [0] "BCD-1547", 
#   [1] "BCD-1547" 
#  ] 
# } 

は、あなたがやりたいために、最後の句でdo_something unless f.first[:ID] == l.first[:ID]代わりの[f.first[:ID], l.first[:ID]]を入れてください。

0

すべてのハッシュが同じ3つのキーとなし、他のキーを持っている場合は、ハッシュは、同様に他のキーを持っている可能性がある場合、あなたは次のように書くことができます単に

new_array1 & new_array2 
    #=> [{:index=>4, :column=>0, :ID=>"ABC"}, 
    # {:index=>4, :column=>2, :ID=>"BCD-1547"}] 

です。

new_array1 = [{:index=>4, :column=>0, :ID=>"ABC",  :pet=>"cat"}, 
       {:index=>4, :column=>1, :ID=>"XYZ",  :bet=>"red"}, 
       {:index=>4, :column=>2, :ID=>"BCD-1547", :met=>"Betty"}] 

new_array2 = [{:index=>4, :column=>0, :ID=>"ABC",  :tree=>"maple"}, 
       {:index=>4, :column=>1, :ID=>"IJK",  :colour=>"blue"}, 
       {:index=>4, :column=>2, :ID=>"BCD-1547", :car=>"beemer"}] 

keys = [:index,:column,:ID] 
h1 = new_array1.each_with_object({}) { |g,h| h[g.select { |k,_| keys.include? k }] = g } 
    #=> {{:index=>4, :column=>0, :ID=>"ABC"}=> 
    #  {:index=>4, :column=>0, :ID=>"ABC", :pet=>"cat"}, 
    # {:index=>4, :column=>1, :ID=>"XYZ"}=> 
    #  {:index=>4, :column=>1, :ID=>"XYZ", :bet=>"red"}, 
    # {:index=>4, :column=>2, :ID=>"BCD-1547"}=> 
    #  {:index=>4, :column=>2, :ID=>"BCD-1547", :met=>"Betty"}} 
h2 = new_array2.each_with_object({}) { |g,h| h[g.select { |k,_| keys.include? k }] = g } 
    #=> {{:index=>4, :column=>0, :ID=>"ABC"}=> 
    #  {:index=>4, :column=>0, :ID=>"ABC", :tree=>"maple"}, 
    # {:index=>4, :column=>1, :ID=>"IJK"}=> 
    #  {:index=>4, :column=>1, :ID=>"IJK", :colour=>"blue"}, 
    # {:index=>4, :column=>2, :ID=>"BCD-1547"}=> 
    #  {:index=>4, :column=>2, :ID=>"BCD-1547", :car=>"beemer"}} 
(h1.keys & h2.keys).map { |k| [h1[k], h2[k]] } 
    #=> [[{:index=>4, :column=>0, :ID=>"ABC", :pet=>"cat"}, 
    #  {:index=>4, :column=>0, :ID=>"ABC", :tree=>"maple"}], 
    # [{:index=>4, :column=>2, :ID=>"BCD-1547", :met=>"Betty"}, 
    #  {:index=>4, :column=>2, :ID=>"BCD-1547", :car=>"beemer"}]] 
+0

ありがとう、Cary。しかし、どのようなタイプのデータ構造体「h1、h2'、および '(h1.keys&h2.keys)」を理解するのに問題があります。マップ{| k | [h1 [k]、h2 [k]]}が成立する。 h1とh2はハッシュですが、3番目の配列は配列の配列です。これを確認できますか? – danynl

+0

'h1'と' h2'は本当にハッシュで、そのキーもハッシュです。 'h1.keys'と' h2.keys'はハッシュの配列であり、その交差は 'h1'と' h2'の両方のキーであるハッシュの配列です。私が行ったのは、 'new_array1'と' new_array2'で各ハッシュの3つの重要なキーを取得し、すべてのハッシュが同じ3つのキーと他のものを持たない場合のように、その交点を取得します。最後のステップは、その交差点を 'h1'と' h2'と一緒に使って望みの結果を得ることです。 –

+0

ありがとう、私はここで別の問題に遭遇した場合、あなたが大いに感謝する外観にすることができます http://stackoverflow.com/questions/39868693/ruby-array-error-typeerror-cant-convert-symbol-into -integer – danynl

関連する問題