I have an array of objects that needs sorting by last name, however the object only has firstname and fullname parameters, so for last name I have to use fullname.replace((firstname " "), ""). Example array below.
const names = [
{
firstname: "John",
fullname: "John Doe"
},
{
firstname: "Amber",
fullname: "Amber Smith"
},
{
firstname: "Michael",
fullname: "Michael Smith"
},
{
firstname: "Jessica",
fullname: "Jessica Kelly Charles"
}
]
While I can use the "replace" every time inside a sort compare function, I'd much rather have something like this:
names.sort(function(a, b) {
const lastname = fullname.replace((firstname " "), "");
if (a.lastname < b.lastname) {
return -1;
} else if (a.lastname > b.lastname) {
return 1;
}
return 0;
});
Obviously lastname comes up as undefined. This has been rather hard to google for, and I think I'm missing some JavaScript basics here, but would greatly apprecite your help in helping me learn to write better code.
CodePudding user response:
You are just declaring a new variable trying to access it via object's property. You should map your data in the first place like:
const names = [
{
firstname: "John",
fullname: "John Doe"
},
{
firstname: "Amber",
fullname: "Amber Smith"
},
{
firstname: "Michael",
fullname: "Michael Smith"
},
{
firstname: "Jessica",
fullname: "Jessica Kelly Charles"
}
].map(person => ({
...person,
lastName: person.fullName.replace(person.firstName ' ', '')
}));
After mapping your data like that, you can use .lastName in the place you need.
names.sort(function(a, b) {
if (a.lastName < b.lastName) {
return -1;
} else if (a.lastName > b.lastName) {
return 1;
}
return 0;
});
CodePudding user response:
Your best bet is to modify the source of the array so it stores lastname upon collection.
If you can't do that:
Unless you do a prep pass through your array adding a lastname property, you'll have to compute it each and every time your sort callback is called, for both a and b.
names.sort((a, b) => {
const alast = a.fullname.replace(a.firstname " "), "");
const blast = b.fullname.replace(b.firstname " "), "");
return alast.localeCompare(blast);
});
(Note I used localeCompare, which is always a better choice for names and other natural language strings than < and >. For instance, ask the French whether ç should really come after z as it does with < and >. ;-) )
That will recompute the lastname for the same object repeatedly, though, since the same object may be passed to sort (as either a or b) repeatedly. If you think that may be a problem, you could do that prep pass I mentioned:
// Build a map of entry to last names
const lastnames = new Map(names.map(entry => {
const lastname = entry.fullname.replace(entry.firstname " ", "");
return [entry, lastname];
}));
// sort
names.sort((a, b) => {
return lastnames.get(a).localeCompare(lastnames.get(b));
});
