ruby比较不同数组中哈希值之间的值

时间:2016-10-04 09:09:32

标签: arrays ruby hash compare

我有两个不同的数组,每个数组都包含不同的哈希值。

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"}
                ]

仅当:IDnew_array1值相同时,我才想比较new_array2中的:index键与:column中的值的值

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

有没有办法遍历两个数组中的所有哈希并找到匹配?或者也许是一种更优雅的方式在ruby中做到这一点?

3 个答案:

答案 0 :(得分: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中的某个项目与index中的任何项目具有相同的columnIDnew_array2个键,则会包含该项目。

通过使用==比较相等性,你也可以简化这些是哈希中唯一的键:

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

inject方法,别名(也称为reduce)接受一个集合并从中创建一个新值,每次调用inject的块时,都会给出它集合的下一个元素和前一个块的返回值(第一次调用块时,它被赋予传递给inject的种子值)。这允许您构建类似于递归的值。

此处有inject的一些示例:Need a simple explanation of the inject method

只要给定块为任何给定的集合元素返回true,any?方法将返回true。如果块永远不会返回true,则any?返回false。所以:

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

答案 1 :(得分: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]]来做你想做的事。

答案 2 :(得分:0)

如果所有哈希都有相同的三个键而没有其他键,那么它只是

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"}]]