Slick23
Slick23

Reputation: 5897

Is there a way to find out where a number lies in a range in ruby?

Let's say I have a min and a max number. max can be anything, but min will always be greater than zero.

I can get the range min..max and let's say I have a third number, count -- I want to divide the range by 10 (or some other number) to get a new scale. So, if the range is 1000, it would increment in values of 100, 200, 300, and find out where the count lies within the range, based on my new scale. So, if count is 235, it would return 2 because that's where it lies on the range scale.

Am I making any sense? I'm trying to create a heat map based on a range of values, basically ... so I need to create the scale based on the range and find out where the value I'm testing lies on that new scale.

I was working with something like this, but it didn't do it:

def heat_map(project, word_count, division)
    unless word_count == 0
      max = project.words.maximum('quantity')
      min = project.words.minimum('quantity')
      range = min..max
      total = range.count
      break_point = total / division
      heat_index =  total.to_f / word_count.to_f
      heat_index.round
    else
      "freezing"
    end
  end

I figured there's probably an easier ruby way I'm missing.

Upvotes: 1

Views: 480

Answers (3)

dantswain
dantswain

Reputation: 5467

Why not just use arithmetic and rounding? Assuming that number is between min and max and you want the range split into n_div divisions and x is the number you want to find the index of (according to above it looks like min = 0, max = 1000, n_div = 10, and x = 235):

def heat_index(x, min, max, n_div)
  break_point = (max - min).to_f/n_div.to_f
  heat_index = (((x - min).to_f)/break_point).to_i
end

Then heat_index(235, 0, 1000, 10) gives 2.

Upvotes: 4

djb
djb

Reputation: 6011

How's this? It makes an array of range boundaries and then checks if the number lies between them.

def find_range(min, max, query, increment)
  values = []
  (min..max).step(increment) { |value| values << value }
  values.each_with_index do |value, index|
    break if values[index + 1].nil?
    if query > value && query < values[index + 1]
      return index
    end
  end
end

EDIT: removed redundant variable

Upvotes: 1

Michael Kohl
Michael Kohl

Reputation: 66837

I'm just quickly brainstorming an idea, but would something like this help?

>> (1..100).each_slice(10).to_a.index { |subrange| subrange.include? 34 }
=> 3
>> (1..100).each_slice(5).to_a.index { |subrange| subrange.include? 34 }
=> 6

This tells you in which subrange (the subrange size is determined by the argument to each_slice) the value (the argument to subrange.include?) lies.

>> (1..1000).each_slice(100).to_a.index { |subrange| subrange.include? 235 }
=> 2

Note that the indices for the subranges start from 0, so you may want to add 1 to them depending on what you need. Also this isn't ready as is, but should be easy to wrap up in a method.

Upvotes: 4

Related Questions