How to Sort an Associative Array by Its Values in JavaScript

How to sort an associative array by its values in Javascript?

Javascript doesn't have "associative arrays" the way you're thinking of them. Instead, you simply have the ability to set object properties using array-like syntax (as in your example), plus the ability to iterate over an object's properties.

The upshot of this is that there is no guarantee as to the order in which you iterate over the properties, so there is nothing like a sort for them. Instead, you'll need to convert your object properties into a "true" array (which does guarantee order). Here's a code snippet for converting an object into an array of two-tuples (two-element arrays), sorting it as you describe, then iterating over 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 which takes 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>

How to sort an (associative) array by value?

Arrays can only have numeric indexes. You'd need to rewrite this as either an Object, or an Array of Objects.

var status = new Object();
status['BOB'] = 10
status['TOM'] = 3
status['ROB'] = 22
status['JON'] = 7

or

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 with:

status.sort(function(a,b) {
return a.val - b.val;
});

Sorting associative array of objects in javascript

You may use .sort only on arrays due to it is Array.prototype method (MDN). So as an easiest solution I would prefer to reform your columns data from object to array:

var columnList = [
{
"key": "image",
"value": {
"show": false,
"orderable": true,
"value": 0,
"displayOrder":2
}
},
{
"key": "name",
"value": {
"show": true,
"orderable": true,
"value": 1,
"displayOrder":0
}
},
{
"key": "company",
"value": {
"show": false,
"orderable": false,
"value": 2,
"displayOrder":1
}
}
];

var result = columnList.sort(function(a, b) {
return parseFloat(a.value.displayOrder) - parseFloat(b.value.displayOrder);
});

console.log(result);

The result of console.log would be exactly

0:{key: "name", value: {…}}
1:{key: "company", value: {…}}
2:{key: "image", value: {…}}

This transformation (from object to array) could be done programmatically via Object.keys:

result = Object.keys(columns)
.map(c => ({ key: c, value: columns[c]}))
.sort((a, b) => a.value.displayOrder - b.value.displayOrder)

Here the columns is your initial object. With the help of Object.keys() and .map() I turn it into the array I described before, so the .sort() method could be called in a chain.

How to sort an associative array by value and keep values?

There are no associative arrays in JavaScript (setting aside the Map class in ES2015). Object properties cannot be ordered; the runtime delivers property names by all APIs in an arbitrary order.

What you can do is grab the property names into an array via Object.keys() or some equivalent, and then sort that array and access the object properties in order by iterating through that array.

Sorting Javascript associative array values in descending order

You have to return an array of objects if you want ordering. Properties of an object do not have a guaranteed order.

var obj = getWordFrequency(words);
var array = Object.keys(obj).map(function(key){
return {word: key, count: obj[key]};
});
array.sort(function (a,b){ return b.count - a.count});

Typed from my phone, untested, order of a and b may need to be reversed

How to sort associative array in Javascript?

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.

How to re-sort an indexed array of associative arrays, based on the values in the associative arrays?

If you have Bash 4.3 or newer, you can use namerefs for this, as follows:

sort_by() {
local arr field sort_params elem
declare -n arr=$1
field=$2

# Build array with sort parameters
[[ $3 == 'desc' ]] && sort_params+=('-r')
[[ $field == 'age' ]] && sort_params+=('-n')

# Schwartzian transform
for elem in "${arr[@]}"; do
declare -n ref=$elem
printf '%s\t%s\n' "${ref["$field"]}" "$elem"
done | sort "${sort_params[@]}" | cut -f2
}

declare -A assoc1=([name]=aaa [age]=20)
declare -A assoc2=([name]=bbb [age]=40)
declare -A assoc3=([name]=ccc [age]=25)
indexed_array=(assoc1 assoc2 assoc3)

readarray -t byage < <(sort_by indexed_array age desc)
declare -p byage

readarray -t byname < <(sort_by indexed_array name asc)
declare -p byname

The calling syntax is a bit different:

sort_by ARRAYNAME FIELD SORTORDER

and the output is one element per line, so to read it back into an array, we have to use something like readarray (see examples at the end).

First, we use a nameref to assign the arrayname to arr:

declare -n arr=$1

arr now behaves as if it were the actual array.

Then, we build an array with the parameters for sort: if the third parameter is desc, we use -r, and if the field is age, we use -n. This could be made a bit smarter and check if the field contains numeric values or not, and set -n accordingly.

We then iterate over the elements of arr, the elements of which are the names of the associative arrays. In the loop, we assign the names to ref:

declare -n ref=$elem

ref now behaves like the actual associative array.

To sort, we use a Schwartzian transform (decorate – sort – undecorate) by printing lines with the chosen field name and then the array name; for example, for age, we'd get

20      assoc1
40 assoc2
25 assoc3

This is piped to sort with the proper parameters, and with cut -f2 we remove the sort field again.

The output for the examples looks like this:

declare -a byage=([0]="assoc2" [1]="assoc3" [2]="assoc1")
declare -a byname=([0]="assoc1" [1]="assoc2" [2]="assoc3")

Notice that declare -n declares local parameters in the function, so they don't pollute the global namespace.



Related Topics



Leave a reply



Submit