2

I have an object like this:

var rock = {
 5: 0.5,
 0: 0.8,
 10: 0.3,
 2: 1.0,
}

I have a number like 4.3and I need the index and value of the prior and following numer. In this example I would get

var timeA = 2;
var valueA = 1.0
var timeB = 5;
var valueB = 0.5;

My first idea was something like a for-loop, but I don't know how to make sure that it's in the right order.

wernersbacher
  • 1,254
  • 13
  • 29

3 Answers3

2

Because the key ordering of objects isn't guaranteed, you'd have to iterate over all keys and work out the closest lower and higher value:

var rock = {
 0: 0.8,
 2: 1.0,
 5: 0.5,
 10: 0.3
};

var max = Infinity, min = -Infinity;
var to_find = 4.3;

Object.keys(rock).forEach(function(k) {
  var value = +k;

  if (value <= to_find && value > min) {
      min = value;
  } else if (value >= to_find && value < max) {
      max = value;
  }
});

console.log(min, rock[min], max, rock[max]); // 2, 1, 5, 0.5

Note that afterwards min or max may still have their original values, i.e. -Infinity and Infinity, in which case undefined would be yielded when used as a key to rock.

Ja͢ck
  • 161,074
  • 33
  • 239
  • 294
1

You can use the for..in (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in) loop in javascript to loop through the properties of an object. Using that you can test the property name against the given value. Once you have the two properties you can access the property values using them as indices.

var given = 4.3;
var timeA = null;
var timeB = null;
for(var e in rock){
    if(e > given){
        timeB = e;
        break;
    }
    timeA = e;    
}
var valueA = rock[timeA];
var valueB = rock[timeB];

JSFiddle: http://jsfiddle.net/x4hzetw7/

If you wanted this work as you expect however you must find a way to sort the properties. To do that you can follow the link on one of the previous answers (using Object.keys(obj)).

var given = 4.3;
var timeA = null;
var timeB = null;
var keys = Object.keys(rock);
var sorted = keys.map(Number).sort(function(a,b) {return a[0]-b[0];});
for(var i = 0; i < sorted.length; i++){
    var e = keys[i];
    if(e > given){
        timeB = e;
        break;
    }
    timeA = e;    
}
var valueA = rock[timeA];
var valueB = rock[timeB];

Updated JSFiddle: http://jsfiddle.net/x4hzetw7/5/

Gary.S
  • 6,841
  • 1
  • 24
  • 35
  • This assumes the keys are ordered lowest to highest, but that's not guaranteed. – Ja͢ck Mar 05 '15 at 09:11
  • Since you're using `Object.keys()` you might as well use `Array.prototype.map()` et al instead of underscore :) – Ja͢ck Mar 05 '15 at 09:30
  • @Ja͢ck Thanks for the help, i feel at this point your answer should be accepted since you basically wrote both. – Gary.S Mar 05 '15 at 09:35
  • Thanks for the vote :) oh, you should do `.map(Number)` instead of `.map(parseInt)`. – Ja͢ck Mar 05 '15 at 09:37
  • Yes, you _must_ use `Number`. You will get incorrect results if you use `parseInt` because the latter will attempt to use all three parameters passed to the callback. – Alnitak Mar 05 '15 at 09:49
-2

You can do something like this:

for (var i in rock) {
    if (rock.hasOwnProperty(i) && rock[i] !== null) {
        var val = rock[i];
        console.log("rock["+i+"] = ", val);
    }
};

But JS objects aren't natively sorted. You might want to look at this question to understand how it works and what you can do about it.

Community
  • 1
  • 1
casraf
  • 17,682
  • 7
  • 48
  • 83