[英]What is the most idiomatic way to perform multiple tests in ruby?
我有以下邏輯:
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中供以后使用。 如果我找到匹配,我就會突破循環。
我正在尋找最優化這種條件的慣用方法。 先感謝您。
怎么樣:
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
我就是這樣做的。
碼
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
[編輯:在我看到@ 7stud的答案之前,我沒有注意到“3-5”的比賽。 要求匹配數量落在給定范圍內是一個有趣的變化。 這是我如何解決這個要求。
碼
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}]
浪潮]
我認為更可讀的版本是slice
:
keys = [:apples, :oranges, :pinapple]
match = some_array.find {|e| e.slice( *keys ) == another_hash.slice( *keys )}
UPDATE
Slice不是Hash的純ruby方法,它包含在Rails的ActiveSupport庫中。
如果您不想使用Rails,則只需加載Active Support即可。
將active_support添加到您的Gemfile並require "active_support/core_ext/hash/slice"
。
或者您可以將slice.rb的內容粘貼到您的應用程序中。 URL可以在這里找到。
如果我可以匹配所需的鍵(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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.