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 exactly0:{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
Why and When to Use Default Export Over Named Exports in Es6 Modules
If (Key in Object) or If(Object.Hasownproperty(Key)
JavaScript Listener, "Keypress" Doesn't Detect Backspace
Angularjs Routing 404 Error with HTML5 Mode
JavaScript Roundoff Number to Nearest 0.5
Get Width Height of Remote Image from Url
Remove Zero-Width Space Characters from a JavaScript String
Where Should I Initialize Pg-Promise
What Do Double Brackets Mean in JavaScript and How to Access Them
Unchecked Runtime.Lasterror While Running Tabs.Executescript
How to Detect When a Tab Is Focused or Not in Chrome with JavaScript
How to Sum the Values of a JavaScript Object
How to Check Dimensions of Image Before Uploading
JavaScript "Variable Variables": How to Assign Variable Based on Another Variable