I've got a ruby array of hashes with two keys, 'tier' and 'price'. For a given price, I want to return the tier.
This is simple enough with exact matching, but how do I ensure I always have a match by rounding my input value up to the next value in the array?
For example, given the array below, if I have a value of '499', I want to return '10'.
tiers = [
{ tier: 0, price: 0 },
{ tier: 1, price: 50 },
{ tier: 2, price: 100 },
{ tier: 3, price: 150 },
{ tier: 4, price: 200 },
{ tier: 5, price: 250 },
{ tier: 6, price: 300 },
{ tier: 7, price: 350 },
{ tier: 8, price: 400 },
{ tier: 9, price: 450 },
{ tier: 10, price: 500 },
{ tier: 11, price: 550 },
{ tier: 12, price: 600 },
{ tier: 13, price: 650 },
{ tier: 14, price: 700 },
{ tier: 15, price: 750 },
{ tier: 16, price: 800 },
{ tier: 17, price: 850 },
{ tier: 18, price: 880 },
{ tier: 19, price: 950 },
{ tier: 20, price: 1000 }
]
I can get an exact match with tiers.detect { |tier| tier[:price] == "500"}[:tier]
, but this will return an error if I don't have a match. I could increment my input value until I return a match but that seems very inefficient.
I considered rounding my input value, but you'll notice that the increment isn't always the same (from tier 17 to 18 the price only increases by 30).
You could enumerate all tiers in pairs and evaluate your price against the pair. Something like this:
def detect_tier(price)
tiers.each_cons(2) do |t1, t2|
next if price < t1[:price] # too low
next if price > t2[:price] # too high
return t1[:tier] if price == t1[:price] # matches tier price exactly
return t2[:tier] # "round up"
end
end
detect_tier(10) # => 1
detect_tier(100) # => 2
detect_tier(499) # => 10
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With