I'm trying to sort an array of objects by multiple properties, specifically due date and name:
const sortByName = (a, b) => {
const lc = x => x.name.toLowerCase();
return lc(a).localeCompare(lc(b));
}
const sortByDueDate = (a, b) => {
const time = x => x.due.getTime();
if (b.due === null)
return -1;
if (a.due === null)
return 1;
return time(a) - time(b);
}
const items = [
{name: 'AItem', due: new Date(2021, 8, 26)},
{name: 'WItem', due: null},
{name: 'TItem', due: new Date(2021, 7, 26)},
{name: 'CItem', due: new Date(2021, 7, 26)},
{name: 'ZItem', due: null},
{name: 'OItem', due: new Date(2021, 1, 11)},
];
console.log(items.sort((a,b) => sortByDueDate(a,b) || sortByName(a,b)));
What complicates things here is that sometimes due dates can be null
. In that case, such items should be moved to the bottom of the sorted array. The two additional conditions in the sortByDueDate
function does exactly that. However, this means that elements with due === null
are no longer sorted by name:
[
{ name: 'OItem', due: 2021-02-10T23:00:00.000Z },
{ name: 'CItem', due: 2021-08-25T22:00:00.000Z },
{ name: 'TItem', due: 2021-08-25T22:00:00.000Z },
{ name: 'AItem', due: 2021-09-25T22:00:00.000Z },
{ name: 'ZItem', due: null },
{ name: 'WItem', due: null }
]
Is there a neat way to fix this, i.e. maintain correct sorting for all elements in the sorted array? I know that I can sort by one property first and then by another but that would mean going through the whole array twice and I'd like to avoid that.