How to sort associative array by its values ​​in javascript?

I have an associative array:

array["sub2"] = 1; array["sub0"] = -1; array["sub1"] = 0; array["sub3"] = 1; array["sub4"] = 0; 

What is the most elegant way of sorting (descent) by its values, where the result will be an array with the corresponding indices in this order:

 sub2, sub3, sub1, sub4, sub0? 
+77
javascript sorting arrays associative
Mar 04 '11 at 10:17
source share
10 answers

Javascript does not have "associative arrays" as you think of them. Instead, you simply have the ability to set the properties of the object using the array type syntax (as in your example), as well as the ability to iterate over the properties of the object.

This means that there is no guarantee regarding the order in which you iterate over properties, so there is nothing like that for them. Instead, you will need to convert your object properties into a "true" array (which guarantees order). Here is a code fragment for converting an object into an array of two tuples (two-element arrays), sorting it as it is described, then repeating it:

 var tuples = []; for (var key in obj) tuples.push([key, obj[key]]); tuples.sort(function(a, b) { a = a[1]; b = b[1]; return a < b ? -1 : (a > b ? 1 : 0); }); for (var i = 0; i < tuples.length; i++) { var key = tuples[i][0]; var value = tuples[i][1]; // do something with key and value } 

You may find it more natural to wrap this in a function that performs a callback:

 function bySortedValue(obj, callback, context) { var tuples = []; for (var key in obj) tuples.push([key, obj[key]]); tuples.sort(function(a, b) { return a[1] < b[1] ? 1 : a[1] > b[1] ? -1 : 0 }); var length = tuples.length; while (length--) callback.call(context, tuples[length][0], tuples[length][1]); } bySortedValue({ foo: 1, bar: 7, baz: 3 }, function(key, value) { document.getElementById('res').innerHTML += `${key}: ${value}<br>` }); 
 <p id='res'>Result:<br/><br/><p> 
+111
Mar 04 2018-11-11T00:
source share

EDIT: people continue to vote for this answer, but it's really old. Please review why you are not just using Object.keys () these days: var keys = Object.keys(obj);

Instead of correcting you in the semantics of the "associative array", I think this is what you want:

 function getSortedKeys(obj) { var keys = []; for(var key in obj) keys.push(key); return keys.sort(function(a,b){return obj[b]-obj[a]}); } 

You put an object (like yours) in a dump and get an array of keys - and these properties - back, sorted in descending (numerical) value, for example, the value of the object, as well.

This only works if your values ​​are numeric. Set up a small function(a,b) to change the sorting mechanism for ascending work or for string values ​​(for example). Left as an exercise for the reader.

+75
Aug 04 2018-12-12T00:
source share

Continued discussion and other solutions discussed in How to sort an (associative) array by value? with a better solution (for my case) using saml (cited below).

Arrays can only have numeric indices. You will need to rewrite this as an object or an array of objects.

 var status = new Array(); status.push({name: 'BOB', val: 10}); status.push({name: 'TOM', val: 3}); status.push({name: 'ROB', val: 22}); status.push({name: 'JON', val: 7}); 

If you like the status.push method, you can sort it using:

 status.sort(function(a,b) { return a.val - b.val; }); 
+15
Oct 08 '12 at 23:27
source share

JavaScript really doesn't have such a thing as an "associative array". What you have is a plain old object. Of course, they work as associative arrays, and keys are available, but there are no semantics around the order of keys.

You can turn your object into an array of objects (key / value pairs) and sort it:

 function sortObj(object, sortFunc) { var rv = []; for (var k in object) { if (object.hasOwnProperty(k)) rv.push({key: k, value: object[k]}); } rv.sort(function(o1, o2) { return sortFunc(o1.key, o2.key); }); return rv; } 

Then you call this using the comparator function.

+5
Mar 04 '11 at 22:30
source share

Here is a ben blank answer if you don't like tuples.

This will save you a few characters.

 var keys = []; for (var key in sortme) { keys.push(key); } keys.sort(function(k0, k1) { var a = sortme[k0]; var b = sortme[k1]; return a < b ? -1 : (a > b ? 1 : 0); }); for (var i = 0; i < keys.length; ++i) { var key = keys[i]; var value = sortme[key]; // Do something with key and value. } 
+4
May 2 '13 at 18:21
source share

No unnecessary complication is required ...

 function sortMapByValue(map) { var tupleArray = []; for (var key in map) tupleArray.push([key, map[key]]); tupleArray.sort(function (a, b) { return a[1] - b[1] }); return tupleArray; } 
+4
Jan 10 '15 at 5:07
source share

I use $ .each jquery, but you can do it with a for loop, the improvement is as follows:

  //.ArraySort(array) /* Sort an array */ ArraySort = function(array, sortFunc){ var tmp = []; var aSorted=[]; var oSorted={}; for (var k in array) { if (array.hasOwnProperty(k)) tmp.push({key: k, value: array[k]}); } tmp.sort(function(o1, o2) { return sortFunc(o1.value, o2.value); }); if(Object.prototype.toString.call(array) === '[object Array]'){ $.each(tmp, function(index, value){ aSorted.push(value.value); }); return aSorted; } if(Object.prototype.toString.call(array) === '[object Object]'){ $.each(tmp, function(index, value){ oSorted[value.key]=value.value; }); return oSorted; } }; 

So now you can do

  console.log("ArraySort"); var arr1 = [4,3,6,1,2,8,5,9,9]; var arr2 = {'a':4, 'b':3, 'c':6, 'd':1, 'e':2, 'f':8, 'g':5, 'h':9}; var arr3 = {a: 'green', b: 'brown', c: 'blue', d: 'red'}; var result1 = ArraySort(arr1, function(a,b){return ab}); var result2 = ArraySort(arr2, function(a,b){return ab}); var result3 = ArraySort(arr3, function(a,b){return a>b}); console.log(result1); console.log(result2); console.log(result3); 
+1
Jul 19 '12 at 13:22
source share

Just like that, there, and someone is looking for tuples based on. This will compare the first element of the object in the array than the second element and so on. then in the example below it will first compare β€œa”, then β€œb”, etc.

 let arr = [ {a:1, b:2, c:3}, {a:3, b:5, c:1}, {a:2, b:3, c:9}, {a:2, b:5, c:9}, {a:2, b:3, c:10} ] function getSortedScore(obj) { var keys = []; for(var key in obj[0]) keys.push(key); return obj.sort(function(a,b){ for (var i in keys) { let k = keys[i]; if (a[k]-b[k] > 0) return -1; else if (a[k]-b[k] < 0) return 1; else continue; }; }); } console.log(getSortedScore(arr)) 

Outputs

  [ { a: 3, b: 5, c: 1 }, { a: 2, b: 5, c: 9 }, { a: 2, b: 3, c: 10 }, { a: 2, b: 3, c: 9 }, { a: 1, b: 2, c: 3 } ] 
0
Jun 27 '17 at 10:45
source share

In my opinion, the best approach for a particular case is the one that is offered as a regular pike. The slight improvement I would suggest works in modern browsers:

 // aao is the "associative array" you need to "sort" Object.keys(aao).sort(function(a,b){return aao[b]-aao[a]}); 

This can be easily applied and works great in this particular case, so you can do:

 let aoo={}; aao["sub2"]=1; aao["sub0"]=-1; aao["sub1"]=0; aao["sub3"]=1; aao["sub4"]=0; let sk=Object.keys(aao).sort(function(a,b){return aao[b]-aao[a]}); // now you can loop using the sorted keys in 'sk' to do stuffs for (let i=sk.length-1;i>=0;--i){ // do something with sk[i] or aoo[sk[i]] } 

In addition, I provide here a more β€œuniversal” function that you can use to sort even in a wider range of situations, and which combines the improvements that I just proposed with the approaches of Ben Blanck's answers (sorting also string values) and PopeJohnPaulII (sorting by a specific object field / property) and allows you to decide whether you want to use ascending or descending order, here it is:

 // aao := is the "associative array" you need to "sort" // comp := is the "field" you want to compare or "" if you have no "fields" and simply need to compare values // intVal := must be false if you need comparing non-integer values // desc := set to true will sort keys in descendant order (default sort order is ascendant) function sortedKeys(aao,comp="",intVal=false,desc=false){ let keys=Object.keys(aao); if (comp!="") { if (intVal) { if (desc) return keys.sort(function(a,b){return aao[b][comp]-aao[a][comp]}); else return keys.sort(function(a,b){return aao[a][comp]-aao[a][comp]}); } else { if (desc) return keys.sort(function(a,b){return aao[b][comp]<aao[a][comp]?1:aao[b][comp]>aao[a][comp]?-1:0}); else return keys.sort(function(a,b){return aao[a][comp]<aao[b][comp]?1:aao[a][comp]>aao[b][comp]?-1:0}); } } else { if (intVal) { if (desc) return keys.sort(function(a,b){return aao[b]-aao[a]}); else return keys.sort(function(a,b){return aao[a]-aao[b]}); } else { if (desc) return keys.sort(function(a,b){return aao[b]<aao[a]?1:aao[b]>aao[a]?-1:0}); else return keys.sort(function(a,b){return aao[a]<aao[b]?1:aao[a]>aao[b]?-1:0}); } } } 

You can test the functionality using something like the following code:

 let items={}; items['Edward']=21; items['Sharpe']=37; items['And']=45; items['The']=-12; items['Magnetic']=13; items['Zeros']=37; //equivalent to: //let items={"Edward": 21, "Sharpe": 37, "And": 45, "The": -12, ...}; console.log("1: "+sortedKeys(items)); console.log("2: "+sortedKeys(items,"",false,true)); console.log("3: "+sortedKeys(items,"",true,false)); console.log("4: "+sortedKeys(items,"",true,true)); /* OUTPUT 1: And,Sharpe,Zeros,Edward,Magnetic,The 2: The,Magnetic,Edward,Sharpe,Zeros,And 3: The,Magnetic,Edward,Sharpe,Zeros,And 4: And,Sharpe,Zeros,Edward,Magnetic,The */ items={}; items['k1']={name:'Edward',value:21}; items['k2']={name:'Sharpe',value:37}; items['k3']={name:'And',value:45}; items['k4']={name:'The',value:-12}; items['k5']={name:'Magnetic',value:13}; items['k6']={name:'Zeros',value:37}; console.log("1: "+sortedKeys(items,"name")); console.log("2: "+sortedKeys(items,"name",false,true)); /* OUTPUT 1: k6,k4,k2,k5,k1,k3 2: k3,k1,k5,k2,k4,k6 */ 

As I said, you can iterate over sorted keys if you need to do things

 let sk=sortedKeys(aoo); // now you can loop using the sorted keys in 'sk' to do stuffs for (let i=sk.length-1;i>=0;--i){ // do something with sk[i] or aoo[sk[i]] } 

Last but not least, some useful links to Object.keys and Array.sort

0
Jun 30 '18 at 16:20
source share

@commonpike's answer is "correct", but as he continues to comment ...

most browsers now support Object.keys()

Yes ... Object.keys() WAY better.

But which is even better ? Spirit, this is it in coffeescript !

 sortedKeys = (x) -> Object.keys(x).sort (a,b) -> x[a] - x[b] sortedKeys 'a' : 1 'b' : 3 'c' : 4 'd' : -1 

[ 'd', 'a', 'b', 'c' ]

-four
Nov 03 '15 at 3:00
source share



All Articles