I have an array of objects with name & number properties, with name holding String values and number holding Integers. How can I sort the array using .sort() and a compare function, so that objects with a name property with a certain value appear on top, and then the objects with that name are sorted by the values of their number properties in descending order, and lastly, the object which do not have the name value are sorted in descending order by their names, and then by their values? (Sorry for the long sentence).
For example, I have the following array of objects:
let obj = [
{'name': 'Seller','number': 2},
{'name': 'alvino','number': 9},
{'name': 'nick','number': 6},
{'name': 'lee','number': 2},
{'name': 'Seller','number': 1},
{'name': 'Kevin','number': 4},
{'name': 'Brady','number': 2},
{'name': 'Seller','number': 3},
{'name': 'Alvino','number': 3},
]
I would like that array of objects to result like the following:
[
{ name: 'Seller', 'number': 1 },
{ name: 'Seller', 'number': 2 },
{ name: 'Seller', 'number': 3 },
{ name: 'Alvino', 'number': 9 },
{'name':'Alvino','number': 3},
{ name: 'Brady', 'number': 2 },
{ name: 'Kevin', 'number': 4 },
{ name: 'Lee', 'number': 2 },
{ name: 'Nick', 'number': 6 },
]
So far, I can sort them first by name equaling ‘Seller’, and by number in descending order:
[
{ name: 'Seller', helpful: 1 },
{ name: 'Seller', helpful: 2 },
{ name: 'Seller', helpful: 3 },
{ name: 'Lee', helpful: 2 },
{ name: 'Brady', helpful: 2 },
{ name: 'Alvino', helpful: 3 },
{ name: 'Kevin', helpful: 4 },
{ name: 'Nick', helpful: 6 },
{ name: 'Alvino', helpful: 9 }
]
, but I am not sure how sort by if name equals ‘Seller’, then by name in descending order, then by number in descending order. Actually, I am not sure if it would be possible to do all three in one comparison function with the sort method, but would like to hear some thoughts on this.
The code I have so far to return by name equaling ‘Seller’ and then by number in descending order is below (with a commented code that I tried out, but did not work as intended):
let sorted = obj.sort((a, b) => {
if (a.name === 'Seller' && b.name === 'Seller') return a.helpful - b.helpful;
if (a.name === 'Seller') return -1;
if (a.name === 'Seller') return 1;
// if (a.name !== 'Seller' && b.name !== 'Seller') return a.name - b.name;
return a.helpful - b.helpful;
});
3
Answers
An straightforward approach could be to equate the
Seller
values to empty strings before comparing:This of course assumes that you otherwise have no empty string names to compare to.
Just to reiterate what you’ve said:
Essentially, for each sort, a positive or negative comparison justifies an immediate return and falls through to subsequent comparisons only if the prior comparison is zero (i.e. equal).
The following snippet works with any value of the
name
attribute, including the empty string:The two "or" operators (
||
) work on two levels: first thea.name
andb.name
are checked against the value "Seller". If only one of them has that value then the expression before the first||
will evaluate to a non-zero value and the expression after the||
will not be evaluated anymore. The same goes for the expression after the second||
operator. This last expression (the numerical comparison of thehelpful
attributes) will only take place if all other comparison before it resulted in0
.