tags:

views:

6026

answers:

7

Let's say I have a Javascript associative array (a.k.a. hash, a.k.a. dictionary):

var a = new Array();
a['b'] = 1;
a['z'] = 1;
a['a'] = 1;

How can I iterate over the keys in sorted order? If it helps simplify things, I don't even need the values (they're all just the number 1).

+1  A: 

Get the keys in the first for loop, sort it, use the sorted result in the 2nd for loop.

var a = new Array();
a['b'] = 1;
a['z'] = 1;
a['a'] = 1;

var b = [];
for (k in a) b.push(k);
b.sort();
for (var i = 0; i < b.length; ++i) alert(b[i]);
pts
using for (k in b)on an array will cause issues. Iterate with an integer
Luke Schafer
I'm afraid in the last line you wanted to iterate over array `b`, and not `k` which you used to hold the current value of array `a`.
Török Gábor
Thanks for all the fixes.
pts
+17  A: 

You cannot iterate over them directly, but you can find all the keys and then just sort them.

var a = new Array();
a['b'] = 1;
a['z'] = 1;
a['a'] = 1;    

function keys(obj)
{
    var keys = [];

    for(var key in obj)
    {
        keys.push(key);
    }

    return keys;
}

keys(a).sort(); // ["a", "b", "z"]

However there is no need to make the variable 'a' an array. You are really just using it as an object and should create it like this:

var a = {};
a["key"] = "value";
Matthew
You should always check in the `for` loop if `obj.hasOwnProperty(key)`.
Török Gábor
Its working for me.
Lalit
+1  A: 

you could even prototype it onto object:

Object.prototype.iterateSorted = function(worker)
{
    var keys = [];
    for (var key in this)
    {
        if (this.hasOwnProperty[key])
            keys.push(key);
    }
    keys.sort();

    for (var i = 0; i < keys.length; i++)
    {
        worker(this[key]);
    }
}

and the usage:

var myObj = { a:1, b:2 };
myObj.iterateSorted(function(value)
{
    alert(value);
}
Luke Schafer
Since JavaScript is case-sensitive, you should capitalize thw word `object`, because `typeof object // undefined`.
Török Gábor
yes. that was a typo :)
Luke Schafer
+1  A: 

There's no concise way to directly manipulate the "keys" of a Javascript object. It's not really designed for that. Do you have the freedom to put your data in something better than a regular object (or an Array, as your sample code suggests)?

If so, and if your question could be rephrased as "What dictionary-like object should I use if I want to iterate over the keys in sorted order?" then you might develop an object like this:

var a = {
  keys : new Array(),
  hash : new Object(),
  set : function(key, value) {
    if (typeof(this.hash[key]) == "undefined") { this.keys.push(key); }
    this.hash[key] = value;
  },
  get : function(key) {
    return this.hash[key];
  },
  getSortedKeys : function() {
    this.keys.sort();
    return this.keys;
  }
};

// sample use
a.set('b',1);
a.set('z',1);
a.set('a',1);
var sortedKeys = a.getSortedKeys();
for (var i in sortedKeys) { print(sortedKeys[i]); }

If you have no control over the fact that the data is in a regular object, this utility would convert the regular object to your fully-functional dictionary:

a.importObject = function(object) {
  for (var i in object) { this.set(i, object); }
};

This was a object definition (instead of a reusable constructor function) for simplicity; edit at will.

Travis Wilson
A: 

If possible, I'd rethink how you're storing this data. An array is much better suited to this as it has a native sort() method.

Swingley
A: 
<script type="text/javascript">
    var a = {
        b:1,
        z:1,
        a:1
    }; // your JS Object
    var keys = [];
    for (key in a) {
        keys.push(key);
    }
    keys.sort();
    var i = 0;
    var keyslen = keys.length;
    var str = '';
    //SORTED KEY ITERATION
    while (i < keyslen) {
        str += keys[i] + '=>' + a[keys[i]] + '\n';
        ++i;
    }
    alert(str);
    /*RESULT:
    a=>1
    b=>1
    z=>1
    */
</script>
Fran Corpier
+1  A: 

I agree with Swingley's answer, and I think it is an important point a lot of these more elaborate solutions are missing. If you are only concerned with the keys in the associative array and all the values are '1', then simply store the 'keys' as values in an array.

Instead of:

var a = { b:1, z:1, a:1 };
// relatively elaborate code to retrieve the keys and sort them

Use:

var a = [ 'b', 'z', 'a' ];
alert(a.sort());

The one drawback to this is that you can not determine whether a specific key is set as easily. See this answer to javascript function inArray for an answer to that problem. One issue with the solution presented is that a.hasValue('key') is going to be slightly slower than a['key']. That may or may not matter in your code.

Grant Wagner