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 :)
An immediate solution to this would be to store data in an array and use the object to simply store the index in the array at which an object exists.
The basic idea is to use an ordered structure, in this case the array, to hold the data in a sequential manner. In this case, next and prev are both constant time, add is amortized constant time, and delete is O(N).
The ordering of keys isn't guaranteed by the ECMA standard, so
for/in
doesn't need to be in the order keys were added (though in practice, that does tend to be the common implementation). In this solution, I use an array to explicitly keep track of insert order.Edit: I overlooked a deletion issue earlier with splice. The index would become incorrect for all values after the spliced value for a remove. The fix doesn't impact the running time complexity of the operation. A faster version with fewer removes could let the array become sparse and instead of splicing, simply set the index to null to free any reference stored there. This would lower the remove operation to O(1).
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:
Then the
next
function can be something like:In case
key
does not exist ondb
or it was the last one,next
returnsundefined
. 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 returningdb[i + 1].value
directly.You can also use some of Underscore.js utility methods to make
next
simpler:(in this case
next
could returnfalse
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 usingObject.keys
to simplify the job of iterating over the array:Using undercore.js, you can take the keys of an object and do the trick. But I'm not sure if the key-value pairs are ordered in any way to begin with:
jsFiddle: http://jsfiddle.net/QWhN2/
ts / es6 version. I simply get the keys from the storeObject, look for the next Index.