Reputation: 167
I have an array containing several objects similar to the following:
{person: {name: "Steve", id: 1}, role: 1}
{person: {name: "Phil", id: 2}, role: 1}
{person: {name: "Steve", id: 1}, role: 3}
{person: {name: "Phil", id: 2}, role: 6}
My intention is to return an array of the same type, but I'd like to return only one object per "person" with their highest role.
I understand the following will give me a single object with the highest role.
array.reduce((prev, cur) => prev.role > cur.role ? prev : cur);
How do I return each unique person and their corresponding highest role as a new array?
Like so:
{person: {name: "Steve", id: 1}, role: 3}
{person: {name: "Phil", id: 2}, role: 6}
Upvotes: 2
Views: 74
Reputation: 5941
You could use Array.prototype.reduce
and build out an object literal like below. Use the person.name
property value as the object key and then just update the role value if you find a higher value:
var people = [{
person: {
name: "Steve",
id: 1
},
role: 1
}, {
person: {
name: "Phil",
id: 2
},
role: 1
}, {
person: {
name: "Steve",
id: 1
},
role: 3
}, {
person: {
name: "Phil",
id: 2
},
role: 6
}];
var highRoleByPerson = people.reduce((accum, el) => {
if (accum[el.person.name]) {
if (el.role > accum[el.person.name].role) {
accum[el.person.name].role = el.role;
}
} else {
accum[el.person.name] = {
person: {
name: el.person.name,
id: el.person.id
},
role: 0
};
}
return accum;
}, {});
console.log(highRoleByPerson);
Upvotes: 1
Reputation: 193248
Group the items by person.id
with Array.reduce()
, but for each id
store only the object with the highest role. Convert back to array using Object.values()
:
const data = [{ person: { name: "Steve", id: 1 }, role: 1 }, { person: { name: "Phil", id: 2 }, role: 1 }, { person: { name: "Steve", id: 1 }, role: 3 }, { person: { name: "Phil", id: 2 }, role: 6 }];
const result = Object.values(data.reduce((r, o) => {
const id = o.person.id;
if(!r[id] || r[id].role < o.role) r[id] = o;
return r;
}, []));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 1
Reputation: 386868
You need to collect the objects and if you have already one with the same id
check the role
and take the greater one.
var data = [{ person: { name: "Steve", id: 1 }, role: 1 }, { person: { name: "Phil", id: 2 }, role: 1 }, { person: { name: "Steve", id: 1 }, role: 3 }, { person: { name: "Phil", id: 2 }, role: 6 }],
grouped = data.reduce((r, o) => {
var index = r.findIndex(({ person: { id } }) => id === o.person.id);
if (index === -1) {
r.push(o);
return r;
}
if (r[index].role < o.role) {
r[index] = o;
}
return r;
}, []);
console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 4