Reputation: 351
Is there a more efficient way to sort an array based on multiple values of the same attribute in Javascript? I have the following function:
var p1 = [];
var p2 = [];
var p3 = [];
for (var i = 0; i < contentData.length; i++) {
if (contentData[i].priority === 1) {
p1.push(contentData[i]);
}
else if (contentData[i].priority === 2) {
p2.push(contentData[i]);
}
else if (contentData[i].priority === 3) {
p3.push(contentData[i]);
}
}
p1.sort(sortByDateDesc);
p2.sort(sortByDateDesc);
p3.sort(sortByDateDesc);
contentData = p1;
Array.prototype.push.apply(contentData, p2);
Array.prototype.push.apply(contentData, p3);
First I need to sort the array by its priority
attribute, and then by its date
attribute, which is done in the function sortByDateDesc
. Can this be done in a more efficient way?
Thanks!
Sample array:
var data1 = {"title": "His face looks like the best chair", "text": "So there’s this really hot kid in my creative writing class. And everyone knows I like him." +
"But one day, he walked in looking like a freaking GQ model, and I accidentally out loud whispered “Shit, his face looks like the best chair” and the girl who sits " +
"in front of me turned around and said “WTH, that’s freaky and gross” and she moved her seat." +
"She gives me weird looks every time she sees me now.", "url": "http://www.catfacts.co", "user": "Kash Muni", "timestamp": Date.now(), "read":0, "priority":2};
sortByDateDesc function:
function sortByDateDesc(a, b) {
if (a.timestamp > b.timestamp)
return -1;
if (b.timestamp > a.timestamp)
return 1;
return 0;
}
Upvotes: 1
Views: 1218
Reputation: 528
You are on the right track with your sortByDate
function, which is passed in to the .sort()
method as the "CompareFunction".
The CompareFunction that you provide will be passed two parameters, which are by-convention called "a" and "b", and must provide an answer which denotes their relative position:
It is entirely up to you how the CompareFunction deals with those objects. You might only compare a single property, compare multiple properties, or even perform complex processing within your function (but don't).
For comparisons which are numeric in nature, you can arithmetically determine the answer. E.g.
function sortNumbersInAscendingOrder(a, b) {
return a - b;
}
If a > b then a - b results in a positive answer, which states that 'a comes after b'.
Comparing strings is a bit different as the comparison operators return a boolean value. However, you don't actually need to provide all three variants of answer from your CompareFunction - you are allowed to favour one of your objects and say that it comes first even when they're the same. This allows you to sort strings simply using the ternary operator. E.g.
function sortStringsAlphabeticalOrder(a, b) {
// Note: this is a case sensitive sort!
return (a <= b) ? -1 : 1;
}
As usual, the Mozilla docs provide an excellent technical answer: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
Upvotes: 1
Reputation: 350127
You can use the ||
in the custom callback function. Something like this:
contentData.sort( (a, b) => a.priority - b.priority || b.timestamp - a.timestamp );
Only when a.priority - b.priority
is zero (they are equal) will the second part of the expression be evaluated, which exactly when you want the date to play a role.
Swap a.timestamp
and b.timestamp
if the date order has to be ascending instead.
Upvotes: 6