Reputation: 363
I have an array of objects:
var arr = [
{title:'50 - 50'},
{title:'100 - 100'},
{title:'50 - 65'},
{title:'100 - 125'}
];
I'm attempting to sort this array so that the items appear in the following order:
var arr = [
{title:'50 - 50'},
{title:'50 - 65'},
{title:'100 - 100'},
{title:'100 - 125'}
];
Currently I'm using the following sorting function to attempt this:
arr.sort(function(a, b){
var titleA = a.title;
var titleB = b.title;
var arrA = titleA.split(' - ');
var arrB = titleB.split(' - ');
var keyA = parseInt(arrA[0]),
keyB = parseInt(arrB[0]);
// Compare the 2 keys
if(keyA < keyB) return -1;
if(keyA > keyB) return 1;
return 0;
});
However, this returns the items in the following order:
var arr = [
{title:'50 - 65'},
{title:'50 - 50'},
{title:'100 - 125'},
{title:'100 - 100'}
];
It looks like I need to sort by the first number in the title and then the second number. Any ideas?
Upvotes: 24
Views: 53527
Reputation: 9408
Another possibility is to compose a sort function based off of multiple comparator functions. Here is an example function that would do this:
function makeMultiCriteriaSort (...criteria) {
return (a, b) => {
for (let i = 0; i < criteria.length; i++) {
const curCriteriaComparatorValue = criteria[i](a, b)
// if the comparison objects are not equivalent, return the value obtained
// in this current criteria comparison
if (curCriteriaComparatorValue !== 0) {
return curCriteriaComparatorValue
}
}
return 0
}
}
// sort an array with multiple criteria
arr.sort(makeMultiCriteriaSort(comparator1, comparator2))
The npm package thenby takes this idea to the next level.
Upvotes: 0
Reputation: 1702
Here is a cleaner and shorter version that does not require a bunch of nested if/else cases:
const sorted = arr.sort((a,b) => {
const [a1, a2] = a.title.split(' - ').map(Number);
const [b1, b2] = b.title.split(' - ').map(Number);
return a1 - b1 || a2 - b2;
});
Upvotes: 37
Reputation: 528
Create a compare function similar to this:
arr.sort(function(a, b){
var titleA = a.title;
var titleB = b.title;
var arrA = titleA.split(' - ');
var arrB = titleB.split(' - ');
var keyA1 = parseInt(arrA[0]),
keyA2 = parseInt(arrA[1]),
keyB1 = parseInt(arrB[0]),
keyB2 = parseInt(arrB[1]),
// Compare the 2 keys
if(keyA1 < keyB1) return -1;
if(keyA1 > keyB1) return 1;
else
{
if(keyA2 < keyB2) return -1;
if(keyA2 > keyB2) return 1;
return 0;
});
Upvotes: 1
Reputation: 16041
In pseudocode, the logic would be the following:
Procedure: comparator(a,b)
a < b
then return -1
a = b
then call comparator(a1, b1)
recursively, where a1
and b1
are the comparable values of the next level in the sorting.a > b
then return 1
In your concrete case, you can do simply do it by modifying your code a bit:
if (keyA < keyB) {
return -1;
} else if (keyA > keyB) {
return 1;
} else { // keyA == keyB
if (titleA < titleB) {
return -1;
} else if (title > titleB) {
return 1;
} else {
return 0;
}
}
Upvotes: 14
Reputation: 733
Try this:
arr.sort(function(a, b){
var titleA = a.title;
var titleB = b.title;
var arrA = titleA.split(' - ');
var arrB = titleB.split(' - ');
var keyA1 = parseInt(arrA[0]), keyA2 = parseInt(arrA[1])
keyB1 = parseInt(arrB[0]), keyB2 = parseInt(arrB[1]);
// Compare the 2 keys
if (keyA1 < keyB1) return -1;
if (keyA1 > keyB1) return 1;
if (keyA2 < keyB2) return -1;
if (keyA2 > keyB2) return 1;
return 0;
});
Upvotes: 20