4

I need to sort associative array by JS for one of my projects. I found this function, that works great in firefox, but unfortunately it doesnt work in IE8, OPERA, CHROME... Cant find the way to make it work in other browsers, or find another function that would fit the purpose. I really appreciate any help.

function sortAssoc(aInput)
{
    var aTemp = [];
    for (var sKey in aInput) aTemp.push([sKey, aInput[sKey].length]);
    aTemp.sort(function () {return arguments[0][1] < arguments[1][1]});
    var aOutput = new Object();
    //for (var nIndex = aTemp.length-1; nIndex >=0; nIndex--)
    for (var nIndex = 0; nIndex <= aTemp.length-1; nIndex++)
        aOutput[aTemp[nIndex][0]] = aInput[aTemp[nIndex][0]];
    //aOutput[aTemp[nIndex][0]] = aTemp[nIndex][1];
    return aOutput;
}
EboMike
  • 76,846
  • 14
  • 164
  • 167
Santi
  • 43
  • 1
  • 4

3 Answers3

5

This is impossible. An Object in JavaScript (which is what you're using as your "associative array") is specified as having no defined order when iterating over its properties using a for...in loop. You may be able to observe some common ground between some browsers' behaviour, but it's not universal.

Summary: if you need objects in a specific order, use an array.

Tim Down
  • 318,141
  • 75
  • 454
  • 536
1

I know it's an old post but that work :

problem is

aTemp.sort(function () {return arguments[0][1] < arguments[1][1]});

because the sort function attends a number :

aTemp.sort(function (a, b) {
    if (a[1] < b[1])
        return 1;
    else if (a[1] > b[1])
        return -1;
    else
        return 0;
});
Mr.Wizard
  • 24,179
  • 5
  • 44
  • 125
nicolas
  • 11
  • 1
0

I recently ran into this problem and found this question. I was disappointed to find that there was no pre-defined way to sort an associative array, but it made sense and pointed me in the right direction. I didn't fully realize that in JS associative arrays are really objects and are only arrays in name. I had an associative array that contained more associative arrays, ex:

var firstChild = {'id': 0, 'name': 'company Two'};
var secondChild = {'id': 1, 'name': 'company One'};
var parent = {
    'company Two': firstChild,
    'company One': secondChild
};

The following function will sort the above parent array based upon it's keys. For this to work as written, the parent array needs keys that match a value in the associated array. For instance, parent['unique string'] will need to have some key value that holds a value of 'unique string'. In my case, this is the name key; however, you can choose any key you like.

function associativeSort(givenArray, keyToSort) {
    var results = [];

    var temp = [];
    for(var key in givenArray) {
        temp.push(givenArray[key].name);
    }
    temp = temp.sort();
    for(var x = 0; x < temp.length; x++) {
        results[x] = givenArray[temp[x]];
    }

    return results;
}

Given my example array, this function would return:

var parent = {
    'company One': {'id': 1, 'name': 'company One'},
    'company Two': {'id': 0, 'name': 'company Two'}
};

It's a simple solution, but it took me a while to think of. Hope this helps others facing this problem.

David Myers
  • 799
  • 1
  • 9
  • 18
  • I know, it's meant to show the structure, not how you would actually define the array. – David Myers Nov 21 '12 at 04:41
  • Which means that it doesn't show the structure. The pseudocode is ambiguous. It could either mean `{ key : [], key : [] }` or it could mean `[ {key:[]}, {key:[]} ]`. From your code it looks like it means the latter. So you should have written it as such. – slebetman Nov 21 '12 at 05:39
  • Actually, I just read your code, `results[x] = givenArray[x]` doesn't work because x is a number. Perhaps you meant `results[x] = givenArray[temp[x]]` ? – slebetman Nov 21 '12 at 05:41
  • As far as the array is concerned, it's a parent associative array which contains child associative arrays. Also, as far as [] vs {}, you realize that associative arrays in JS are really just objects and are accessed the same way so that's a moot point. And in reference to your question, it's the former, not the latter. Also, I've edited my answer to no longer use pseudocode and to be more clear. – David Myers Nov 21 '12 at 16:36
  • "keyToSort" isn't referenced in your code. Looks like you switched to "key" for short.. – Dss Nov 21 '12 at 17:44
  • @DavidMyers If you clarafication is true, then your code doesn't work. See the accepted answer. You realize that Objects in js doesn't have key ordering. Some browser implementations may have some side-effects that you may have influenced temporarily that may sometimes work in a `for..in` loop but that is not the intent in the js specifications and is not reliable. The only way to process object keys in order is to not use a `for .. in` loop but instead to use a regular for loop iterating over a sorted array of keys. – slebetman Nov 21 '12 at 22:53
  • Reading your code again, the return value is not what you have written. I think you misunderstand your own code. Remember, x is an integer, which means x can never be the string "company One". The result is actually: `[0:{'id': 1, 'name': 'company One'},1:{'id': 2, 'name': 'company Two'}]` – slebetman Nov 21 '12 at 22:58
  • Either I'm not very good at explaining or you're not very good at understanding. This is code that I'm currently using and it works 100%. What I'm doing is essentially this: I have an associative array (or object) that contains associative arrays(or objects). I want to sort the child arrays based upon one of their common key names. So I'm creating a temporary array of those values and I sort it then using that sorted array I re-create the original array using the order of the sorted temporary array. – David Myers Nov 21 '12 at 23:17