Reputation: 485
I am trying to sort array by three columns. Below is my sample array. Sometime, the column can be null too, so I do a checking in my sort function. However, now I would like to sort the name first and then salary and then bonus. How can I achieve that?
let employees = [
{name: 'John', salary: 90000, bonus: 1000},
{name: 'David', salary: 90000, bonus: 1200},
{name: 'Ana', salary: 80000, bonus: 3000}
];
// Code for sorting salary first and then bonus:
function sort(a,b) {
if (a.salary=== null && b.salary=== null ){
return a.bonus- b.bonus;
}
else if (a.salary!== null && b.salary=== null ){
return -1;
}
else if (a.salary=== null && b.salary!== null){
return 1;
}else if (a.salary!== null && b.salary!== null){
return a.salary- b.salary;
}
else {
return 1;
}
}
employees.sort(sort);
console.log(employees);
Upvotes: 0
Views: 563
Reputation: 43728
Just return the first non-zero compare value.
I've also made sure anything that's not a number would be sorted last, but if you are certain that you will only get a valid number or null
then you can simplify the checks.
const employees = [
{name: 'Ana', salary: null, bonus: 3000},
{name: 'Ana', salary: 80000, bonus: 3000},
{name: 'Ana', salary: 70000, bonus: 3000},
{name: 'Ana', salary: 70000, bonus: 1000}
];
employees.sort((a, b) => {
return a.name.localeCompare(b.name) ||
safeNumCompare(a.salary, b.salary) ||
safeNumCompare(a.bonus, b.bonus);
});
console.log(employees);
function safeNumCompare(a, b) {
const aValid = isValidNum(a), bValid = isValidNum(b);
if (!(aValid || bValid)) return 0;
if (!aValid) return 1;
if (!bValid) return -1;
return a - b;
}
function isValidNum(num) {
return typeof num === 'number' && !isNaN(num);
}
Upvotes: 1
Reputation: 24945
You can use this logic:
null
, so better to default.
0
for ascendingInfinity
for descendinga - b
operation for ascending. ||
so that if first equation returns 0, it'll check for next priorityNote:
Above logic will sort in ascending of name then salary and then bonus. So if both users have same salary, then their bonus will be checked and sorted in that fashion.
let employees = [{ name: 'John', salary: 90000, bonus: 1000 }, { name: 'David', salary: 90000, bonus: 1200}, { name: 'David', salary: null, bonus: 1200}, { name: 'Ana', salary: 80000, bonus: 3000}, { name: 'Ana', salary: 80000, bonus: null }];
function sort(a, b) {
return (a.name.localeCompare(b.name)) ||
((a.salary || Infinity) - (b.salary || Infinity)) ||
((a.bonus || 0) - (b.bonus || 0));
}
employees.sort(sort);
console.log(employees);
As rightly suggested by plalx
He wanted nulls sorted last though and by name first as well.
Hence using Infinity
for defaulting salary
Upvotes: 1
Reputation: 956
There is an npm package called lodash. You can achieve your required functionality with their sortBy method.
const _ = require('lodash');
let employees = [
{name: 'John', salary: 90000, bonus: 1000},
{name: 'David', salary: 90000, bonus: 1200},
{name: 'Ana', salary: 80000, bonus: 3000}
];
const sortedArray = _.sortBy(employees, ['name', 'salary', 'bonus']);
I hope it helps.
Upvotes: 1