我有以下逻辑:
some_array.each do |element|
if element[:apples] == another_hash[:apples] &&
element[:oranges] == another_hash[:oranges] &&
element[:pineapple] == another_hash[:pineapple]
match = element
break
end
end
我遍历键值对列表。如果我可以匹配所需的键(3/5),那么我将元素放在var中供以后使用。如果我找到一个匹配,我就会摆脱循环。
我正在寻找最优化这种条件的惯用方法。提前谢谢。
答案 0 :(得分:4)
怎么样:
match = some_array.find do |element|
[:apples, :oranges, :pinapple].all? {|key| element[key] == another_hash[key]}
end
如果您想从5个键中选择任何至少有3个匹配键的元素,那么:
match = some_array.find do |element|
element.keys.select {|key| element[key| == another_hash[key]}.size > 2
end
答案 1 :(得分:3)
我就是这样做的。
<强>代码强>
def fruit_match(some_array, another_hash, fruit)
other_vals = another_hash.values_at(*fruit)
return nil if other_vals.include?(nil)
some_array.find { |h| h.values_at(*fruit) == other_vals }
end
<强>实施例强>
some_array = [ { apple: 1, orange: 2, pineapple: 3, plum: 4 },
{ apple: 1, cherry: 7, pineapple: 6, plum: 2 },
{ apple: 6, cherry: 2, pineapple: 8, fig: 3 } ]
another_hash = { apple: 6, cherry: 4, pineapple: 8, quamquat: 5 }
fruit = [:apple, :pineapple]
fruit_match(some_array, another_hash, fruit)
#=> { :apple=>6, :cherry=>2, :pineapple=>8, :fig=>3 }
fruit = [:apple, :plum]
fruit_match(some_array, another_hash, fruit)
#=> nil
[编辑:我没注意到&#34; 3-5&#34;比赛直到我看到@ 7stud的回答。要求匹配数量落在给定范围内是一个有趣的变化。以下是我如何解决这一要求。
<强>代码强>
def fruit_match(some_array, another_hash, fruit, limits)
other_vals = another_hash.values_at(*fruit)
some_array.select { |h| limits.cover?(h.values_at(*fruit)
.zip(other_vals)
.count {|e,o| e==o && e}) }
end
示例强>
some_array = [ { apple: 1, orange: 2, pineapple: 1, cherry: 1 },
{ apple: 2, cherry: 7, pineapple: 6, plum: 2 },
{ apple: 6, cherry: 1, pineapple: 8, fig: 3 },
{ apple: 1, banana: 2, pineapple: 1, fig: 3 } ]
another_hash = { apple: 1, cherry: 1, pineapple: 1, quamquat: 1 }
fruit = [:apple, :pineapple, :cherry]
limits = (1..2)
fruit_match(some_array, another_hash, fruit, limits)
#=> [{:apple=>6, :cherry=>1, :pineapple=>8, :fig=>3},
# {:apple=>1, :banana=>2, :pineapple=>1, :fig=>3}]
<强>潮] 强>
答案 2 :(得分:1)
我认为更可读的版本是slice
:
keys = [:apples, :oranges, :pinapple]
match = some_array.find {|e| e.slice( *keys ) == another_hash.slice( *keys )}
<强>更新强>
Slice不是Hash的纯ruby方法,它包含在Rails的ActiveSupport库中。
如果您不想使用Rails,只需加载Active Support即可。
将active_support添加到您的Gemfile和require "active_support/core_ext/hash/slice"
。
或者您可以将slice.rb的内容粘贴到您的应用中。可以找到该网址here。
答案 3 :(得分:1)
如果我可以匹配所需的键(3/5)
我认为任何公布的答案都不会解决这个问题。
target_keys = %i[
apples
oranges
pineapples
strawberries
bananas
]
data = [
{beer: 0, apples: 1, oranges: 2, pineapples: 3, strawberries: 4, bananas: 5},
{beer: 1, apples: 6, oranges: 7, pineapples: 8, strawberries: 9, bananas: 10},
{beer: 2, apples: 6, oranges: 2, pineapples: 3, strawberries: 9, bananas: 10},
]
match_hash = {
apples: 6, oranges: 2, pineapples: 3, strawberries: 9, bananas: 10
}
required_matches = 3
required_values = match_hash.values_at(*target_keys).to_enum
found_match = nil
catch :done do
data.each do |hash|
found_values = hash.values_at(*target_keys).to_enum
match_count = 0
loop do
match_count += 1 if found_values.next == required_values.next
if match_count == required_matches
found_match = hash
throw :done
end
end
required_values.rewind
end
end
p found_match
--output:--
{:beer=>1, :apples=>6, :oranges=>7, :pineapple=>8, :strawberry=>9, :banana=>10