簡體   English   中英

在ruby中執行多項測試的最慣用方法是什么?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM