I'm trying to sort an array of objects by the average
property in descending order - so the largest average
is first - but am not able to using underscore.js. Below is my attempt:
var jsonData = [
{
"title": "Dear Kitten",
"totalCount": 1689,
"average": 241
},
{
"title": "Weird Things All Couples Fight About",
"totalCount": 9966,
"average": 1424
},
{
"title": "If Disney Princesses Were Real",
"totalCount": 16567,
"average": 2367
},
{
"title": "Secret Tricks With Everyday Objects",
"totalCount": 24884,
"average": 3555
},
{
"title": "The Coolest Travel Hacks",
"totalCount": 41847,
"average": 8369
},
{
"title": "5 Ways You're Drinking Coffee Wrong",
"totalCount": 55673,
"average": 7953
},
{
"title": "The Perfect Way To Pour A Beer",
"totalCount": 58097,
"average": 58097
},
{
"title": "Fruit You're Eating Wrong",
"totalCount": 65570,
"average": 32785
},
{
"title": "Your Cat Is Judging You",
"totalCount": 78952,
"average": 11279
},
{
"title": "3rd Date vs 30th Date",
"totalCount": 84394,
"average": 14066
}
];
console.log(_.sortBy(jsonData, "average"));
jsFiddle
The issue here is that you wanted the array to be sorted in descending order by average
, instead of the default ascending order.
You could do this by providing a custom iteratee
to the _.sortBy()
function:
_.sortBy( jsonData, function( item ) { return -item.average; } )
Updated fiddle
But I don't recommend that. It would be much better to simply use the native JavaScript [].sort()
method and provide it a comparison function:
jsonData.sort( function( a, b ) { return b.average - a.average; } )
Better fiddle
If you were sorting a very large array, this would also be faster than using _.sortBy()
. Look at the source code for _.sortBy()
to see why:
_.sortBy = function(obj, iteratee, context) {
iteratee = cb(iteratee, context);
return _.pluck(_.map(obj, function(value, index, list) {
return {
value: value,
index: index,
criteria: iteratee(value, index, list)
};
}).sort(function(left, right) {
var a = left.criteria;
var b = right.criteria;
if (a !== b) {
if (a > b || a === void 0) return 1;
if (a < b || b === void 0) return -1;
}
return left.index - right.index;
}), 'value');
};
It's doing quite a bit of work in addition to the .sort()
call - and this code is just the tip of the iceberg, the helper functions it calls like cb()
do a lot of work too.
Why do all that when it's just as easy to call .sort()
directly yourself?
Also, it takes a close reading of that lengthy .sortBy()
source to be sure that it does a numeric sort instead of a lexicographic sort - and the documentation doesn't say!
A lexicographic sort (aka alphabetic sort) is where the values are sorted as strings, not as numbers. So for example it would use this order:
[ 1424, 2367, 241, ... ]
When you call the native array .sort()
yourself, you can easily verify that it uses a numeric sort: the value b.average - a.average
is always a number.