How to sort an array of objects by a property value with priority in JavaScript?
User case: data should be sorted by custom values, which don’t make logical order. Look at the following data:
const list = [
{ category: 'tv', price: 1400 },
{ category: 'smartphones', price: 590 },
{ category: 'notebooks', price: 1500 },
{ category: 'smartphones', price: 350 }
]
We would like to sort the objects in the following order: smartphones, notebooks, anything else and have no control over the order data is fetched. First, we need to create an object with that is going to hold priorities:
let sortingOrder = {
'smartphones': 1,
'notebooks': 2
}
We are going to use standard array sorting method from the prototype, but need to write a comparison function. Let’s make it take the property name and sorting order as parameters, so it can be reused.
function compare(key, order = 'asc') {
return function (a, b) {
if (!a.hasOwnProperty(key) || !b.hasOwnProperty(key))
return 0;
const first = (a[key].toLowerCase() in sortingOrder) ? sortingOrder[a[key]] : Number.MAX_SAFE_INTEGER;
const second = (b[key].toLowerCase() in sortingOrder) ? sortingOrder[b[key]] : Number.MAX_SAFE_INTEGER;
let result = 0;
if (first < second)
result = -1;
else if (first > second)
result = 1;
return (order === 'desc') ? ~result : result
};
}
We use the comparator function to determine the order from keys. Number.MAX_SAFE_INTEGER is used to be sure note specified elements are always last in undetermined order and we are free to extend sortingOrder object. Finally, (order === ‘desc’) ? ~result : result inverts the comparison result for descending order. Lastly, we sort the array as follows:
list.sort(compare('category'));
// OR
list.sort(compare('category', 'desc'));