我有两个不同的数组,每个数组都由不同的散列组成。
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_array1
中:ID
密钥的值与new_array2
中的值。
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做这件事的一种更优雅的方式?
这将返回一个匹配哈希数组:
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
中的任何项目具有相同的index
、column
和ID
密钥,则该项目将被包括在内。
您还可以通过使用==
比较相等性来简化散列中是否只有这些键:
res = new_array1.inject([]) { |memo, hash| memo << hash if new_array2.any? { |hash2| hash == hash2 }; memo }
inject
方法别名为reduce
,它获取一个集合并从中创建一个新值,每次调用赋予inject
的块时,它都会被赋予集合的下一个元素和上一个块的返回值(第一次调用块时,会被赋予传递给inject
的种子值(。这允许您建立类似于递归的值。
这里有一些inject
的例子:需要简单解释注入方法
一旦给定块对于任何给定集合元素返回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
[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]]
放在最后一个子句中,可以随心所欲。
如果所有哈希都有相同的三个键,而没有其他键,那么它就是
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"}]]