10

Here's the situation. I have a JavaScript object and I need to iterate through it, but the order is very important to maintain. I know that JavaScript object is supposed to be unordered, but I was hoping there was some JavaScript equivalent to the following: http://docs.python.org/2/library/collections.html#collections.OrderedDict

This is the original ordering

{
  082013: {'A': 1, 'B', 3}
  092013: {'A': 2, 'B', 4}
  102013: {'A': 8, 'B', 2}
  112013: {'A': 92, 'B', 67}
  122013: {'A': 64, 'B', 32}
}

Then I iterate through it:

aArray = [];
bArray = [];
$.each(data, function(key, value) {
   aArray.push(value.A);
   bArray.push(value.B);
});

the result (on chrome in particular) seems to render more like this:

aArray = [8, 92, 64, 1, 2];
bArray = [2, 67, 32, 3, 4];

This implies that it does not iterate in order, or goes through it in the order of smallest to largest (102013, 112013, 122013, 092013, 082013)

So how could I iterate this object in order, if I can at all?

CRABOLO
  • 8,605
  • 39
  • 41
  • 68
corvid
  • 10,733
  • 11
  • 61
  • 130
  • 3
    You can first pull the keys from the object into a sorted array, and then use that array to lookup the values in the original object. – js1568 Dec 17 '13 at 17:09
  • Array are actually ordered, why not wrapping your objects in an array? – Boris Guéry Dec 17 '13 at 17:09
  • If you want to iterate over the properties from the smallest to largest, then you can extract the keys, sort them and iterate over the keys. If you want to iterate over them in insertion order, you are out of luck. – Felix Kling Dec 17 '13 at 17:10
  • @adeneo, the OP is aware of this, still it want a way to mix the behavior, which totally feasible with a little work. Read the question. – Boris Guéry Dec 17 '13 at 17:11
  • Just curious, if the dates were change to be 5,4,1,2,3, how would it order them? – Ian Dec 17 '13 at 17:12
  • Given the object above, you want two resulting arrays: `[1,2,8,92,64]` and `[3,4,2,67,32]`, correct? – js1568 Dec 17 '13 at 17:13

3 Answers3

15

Off the top of my head, the only way to do this is get the keys (using Object.keys(myObj)), then sort them (using Array.sort) and go through it that way. The keys are unordered in the actual object.

So it's something like:

    var keys = Object.keys(myObj);
    keys.sort();
    for(var i=0; i<keys.length; ++i){
        //do something with myObj[keys[i]]
    }
willy
  • 1,462
  • 11
  • 12
1

Sorting the keys in advance will ensure that they are in the correct order. Then you can access the values you want. Here is a solution using jQuery for cross-browser compatibility:

var data = {
    '082013': {'A': 1, 'B': 3},
    '092013': {'A': 2, 'B': 4},
    '102013': {'A': 8, 'B': 2},
    '112013': {'A': 92, 'B': 67},
    '122013': {'A': 64, 'B': 32}
}, sortedKeys,
    a = [],
    b = [];

sortedKeys = $.map(data, function(value, key) {
    return key;
  }).sort();

$.each(sortedKeys, function(index, value) {
    a.push(data[value].A);
    b.push(data[value].B);
});
console.log(a, b);
//[1, 2, 8, 92, 64] [3, 4, 2, 67, 32] 

http://jsfiddle.net/UxqpS/1/

js1568
  • 7,012
  • 2
  • 27
  • 47
0

Browsers are somewhat inconsistent in how they iterate over keys in an object. It's been a few years since I did a test of this, but most browsers iterate over the keys in a FIFO fashsion (First In, First Out). I think it was Opera that was problematic because it iterated over they keys in alphabetical order.

The ideal solution is to return an Array to JavaScript if order matters. Otherwise the best you can do is willy's suggestion. Below is a polyfill for the Object.keys method:

Object.keys = Object.keys || function keys(x) {
    var keys = [], key;

    for (key in x) {
        if (x.hasOwnProperty(key)) {
            keys.push(key);
        }
    }

    return keys;
};

A more complete polyfill can be found at MDN: Object.keys Polyfill

Greg Burghardt
  • 17,900
  • 9
  • 49
  • 92