javascriptjsoncoffeescriptunderscore.js

Get next key-value pair in an object


Given a key, I want to find the next property in an object. I can not rely on the keys to be ordered or sequential (they're uuids). Please see below for trivial example of what I want:

var db = {
  a: 1,
  b: 2,
  c: 3
}

var next = function(db, key) {
  // ???
}

next(db, 'a');  // I want 2
next(db, 'b');  // I want 3

I also want a prev() function, but I'm sure it will be the same solution.

This seems like such a trivial problem but I can't for the life of me figure out how to do it.

Happy for the solution to use underscore.js or be written in coffeescript :)


Solution

  • The correct answer is: you can't do that, as objects are unordered as per ECMAScript's spec.

    I'd recommend that you use an ordered structure, like an array, for the purpose of the problem:

    var db = [
      {key: 'a', value: 1},
      {key: 'b', value: 2},
      {key: 'c', value: 3}
    ];
    

    Then the next function can be something like:

    var next = function(db, key) {
      for (var i = 0; i < db.length; i++) {
        if (db[i].key === key) {
          return db[i + 1] && db[i + 1].value;
        }
      }
    };
    

    In case key does not exist on db or it was the last one, next returns undefined. if you're never going to ask for the next of the last item, you can simplify that function by removing the ternary && operator and returning db[i + 1].value directly.

    You can also use some of Underscore.js utility methods to make next simpler:

    var next = function(db, key) {
      var i = _.pluck(db, 'key').indexOf(key);
      return i !== -1 && db[i + 1] && db[i + 1].value;
    };
    

    (in this case next could return false sometimes... but it's still a falsy value :))


    Now, a more pragmatic answer could be that, as most browsers will respect the order in which an object was initialized when iterating it, you can just iterate it with a for in loop as the other answers suggest. I'd recommend using Object.keys to simplify the job of iterating over the array:

    // Assuming that db is an object as defined in the question.
    var next = function(db, key) {
      var keys = Object.keys(db)
        , i = keys.indexOf(key);
      return i !== -1 && keys[i + 1] && db[keys[i + 1]];
    };