Get a hash that matches minimum quantity

I have an array of hashes:

arr_of_hsh =[
  {minimum_quantity: "250", cost: "1.5600"},
  {minimum_quantity: "500", cost: "1.3500"},
  {minimum_quantity: "1000", cost: "1.1800"},
  {minimum_quantity: "2500", cost: "1.0200"}
]

Given a certain amount, I'd like to get the hash whose value for :minimum_quantity is the closest to the amount among those less than or equal to the amount. For example, if the amount was 300, this hash would be returned:

{minimum_quantity: "250", cost: "1.5600"}

and if the amount was 1000:

{minimum_quantity: "1000", cost: "1.1800"}
728x90

2 Answers Get a hash that matches minimum quantity

Keeping your data structure the same I'd say this way

 arr_of_hsh.select { |item| item[:minimum_quantity].to_i <= quantity }.
   max_by { |item| item[:minimum_quantity].to_i }

3 months ago

Here is a single-pass solution.

def f(arr, qty)
  h = arr.min_by do |h|
    n = h[:minimum_quantity].to_i
    n <= qty ? (qty-n) : Float::INFINITY
  end
  h[:minimum_quantity].to_i <= qty ? h : nil 
end

(100..1100).step(100).each { |qty| puts "#{qty}: #{f(arr_of_hsh, qty)}" }
 100: nil
 200: nil
 300: {:minimum_quantity=>"250",  :cost=>"1.5600"}
 400: {:minimum_quantity=>"250",  :cost=>"1.5600"}
 500: {:minimum_quantity=>"500",  :cost=>"1.3500"}
 600: {:minimum_quantity=>"500",  :cost=>"1.3500"}
 700: {:minimum_quantity=>"500",  :cost=>"1.3500"}
 800: {:minimum_quantity=>"500",  :cost=>"1.3500"}
 900: {:minimum_quantity=>"500",  :cost=>"1.3500"}
1000: {:minimum_quantity=>"1000", :cost=>"1.1800"}
1100: {:minimum_quantity=>"1000", :cost=>"1.1800"}

If the method is to be called several times for a given arr_of_hsh, sort arr_of_hsh by decreasing value of arr_by_hsh[:minimum_quantity.to_i and then simply use Enumerable#find.

def f(arr, qty)
  h = arr.find { |h| h[:minimum_quantity].to_i <= qty }
end

arr = arr_of_hsh.sort_by { |h| -h[:minimum_quantity].to_i }
  #=> [{:minimum_quantity=>"2500", :cost=>"1.0200"},
  #    {:minimum_quantity=>"1000", :cost=>"1.1800"}, 
  #    {:minimum_quantity=>"500", :cost=>"1.3500"},
  #    {:minimum_quantity=>"250", :cost=>"1.5600"}]
(100..1100).step(100).each { |qty| puts "#{qty}: #{f(arr, qty)}" }
  #=> (same as above)

3 months ago