6

I have this range of numbers:

0  -------> 25 ------->  80 ------> 150
    small      medium       large

I want to recieve a number between 0 to 150 and to display whether it is small, medium or big. 30 and 45 are medium because they are between 25 and 80 and 5 is small because it is lower than 25.

I want to create a function that does this matching for this object:

var sizeMap = { small : 25, medium : 80, large : 150 }

(assuming that 0 is the lowest number).

The function should look like:

function returnSize(number) {
    for (item in sizeMap)
       ???????
    return size
}

how do I write this function so it can be flexible for adding new categories (for example: 'extra large' : 250). Should I present the object as an array?

Alon
  • 7,618
  • 18
  • 61
  • 99

6 Answers6

3

To have a deterministic output, I'd prefer to have an array ordered by the categories in question:

var categories = [ 
  {label: 'small', upTo: 25}, 
  {label: 'medium', upTo: 80}, 
  {label: 'large', upTo: 150} ];

(you can even create this array from your original sizeMap)

And then you can do:

function getSizeCategory(number, categories) {
  for (var i = 0; i < categories.length; ++i) {
    if (number < categories[i].upTo) {
      return categories[i].label;
    }
  }
  throw new Error("not in range!");
}
Community
  • 1
  • 1
Jordão
  • 55,340
  • 13
  • 112
  • 144
  • that solves also the issues I had with list vs. array - thanks for simplification of it.. – Alon Aug 27 '12 at 21:58
2
function returnSize(number, sizeMap) {
    for (var key in sizeMap) {
       if (number < sizeMap[key]) return key;
    }
    return key;
}
xdazz
  • 158,678
  • 38
  • 247
  • 274
  • I was so caught up in doing it one way I didn't see that that this can be done so easily this way - thanks! :) – Alon Aug 27 '12 at 15:39
  • 1
    When you do `for (x in y)` the order is not guaranteed. In firefox it currently is in the order it was specified, so with the following 2 will be large: `returnSize(20,{ large : 150, medium : 80, small : 25 });` – some Aug 27 '12 at 15:48
  • [ECMAScript 262 5th edition](http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf) Page 92 (104 in pdf): "The mechanics and order of enumerating the properties (step 6.a in the first algorithm, step 7.a in the second) is not specified." – some Aug 27 '12 at 16:14
1

just return the largest value that satisfies the "less than" condition:

function returnSize (number) {
    var item;
    for (item in sizeMap) {
        if (number < sizeMap[item]) { 
            return item;
        }
    }
    return item; // this will return largest size if it gets this far
}
jbabey
  • 45,965
  • 12
  • 71
  • 94
  • I was so caught up in doing it one way I didn't see that that this can be done so easily this way - thanks! :) – Alon Aug 27 '12 at 15:39
  • 1
    When you do `for (x in y)` the order is not guaranteed. In firefox it currently is in the order it was specified, so with the following 2 will be large: `returnSize(20,{ large : 150, medium : 80, small : 25 });` – some Aug 27 '12 at 15:50
  • [ECMAScript 262 5th edition](http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf) Page 92 (104 in pdf): "The mechanics and order of enumerating the properties (step 6.a in the first algorithm, step 7.a in the second) is not specified." – some Aug 27 '12 at 16:15
0

you should use an arra of options. Ordered by DESC.

You test your number against your fist number (the greatest), if you need to respect an upper limit.

And when you number is inferior or equal to a category upper limit, you know which category he belongs.

Perello
  • 633
  • 1
  • 7
  • 22
0

Here you have a solution:

RangeCheck = function(range) {
   this.init(range);
};

RangeCheck.prototype = {
  constructor: RangeCheck,
  /**
   * The range map.
   */
  range: null,
  init: function (range) {
    this.range = range || {};
  },

  putRange: function(name, max) {
    this.range[name] = max;
  },

  check: function(number) {
    for (var key in this.range) {
      if (this.range.hasOwnProperty(key)) {
        if (number <= this.range[key]) {
          return key;
        }
      }
    }
    return key;
  }
};

Use it like this:

var rangeCheck = new RangeCheck({ small : 25, medium : 80, large : 150 });
var message = "15: " + rangeCheck.check(15) + "\n"
    + "25: " + rangeCheck.check(25) + "\n"
    + "85: " + rangeCheck.check(85) + "\n"
    + "850: " + rangeCheck.check(850) + "\n";
alert(message);
rangeCheck.putRange("veryLarge", 300);
var message = "15: " + rangeCheck.check(15) + "\n"
    + "25: " + rangeCheck.check(25) + "\n"
    + "85: " + rangeCheck.check(85) + "\n"
    + "850: " + rangeCheck.check(850) + "\n";
alert(message);

And the jsFiddle: http://jsfiddle.net/xKjt7/

Chango
  • 6,754
  • 1
  • 28
  • 37
0

Just for fun. One liner using underscore:

get_size = function (n) { return _.find(_.map({'small':100, 'big':200}, function (x,i) { return [x < n, i]; }), function (x) { return x[0] == false; })[1];};
Nikolay Fominyh
  • 8,946
  • 8
  • 66
  • 102