I want to sort attendees based on the key groups
which is an array of groups (function like tags). I want to sort by the predefined sortOrder
order and then by if main_contact is true if multiple attendees for the same group exist.
But I'm really stuck with how to check if a groups.name exists and then sort them efficiently by the predefined order.
const attendees = [
{
name: "Peter",
groups: [{ name: "agency", main_contact: false, stand_in_contact: true }],
},
{
name: "Alex",
groups: [{ name: "agency", main_contact: true, stand_in_contact: false }],
},
{
name: "Nina",
groups: [
{ name: "production", main_contact: true, stand_in_contact: false },
],
},
{
name: "Christina",
groups: [
{ name: "client", main_contact: true, stand_in_contact: false },
{ name: "crew", main_contact: false, stand_in_contact: false },
],
},
];
const sortAttendees = (attendees) => {
const sortOrder = ["agency", "client", "production", "crew"];
// return sortOrder.indexOf(a.type) - sortOrder.indexOf(b.type);
if (!attendees || attendees.length == 0) return [];
return attendees.sort((a, b) => {
if (a.groups.some((group) => group.name === "agency")) {
return -1;
}
if (a.groups.some((group) => group.name === "client")) {
return 1;
}
if (a.groups.some((group) => group.name === "production")) {
return 1;
}
return 1;
});
};
Result
const attendees = [
{
name: "Alex",
groups: [{ name: "agency", main_contact: true, stand_in_contact: false }],
},
{
name: "Peter",
groups: [{ name: "agency", main_contact: false, stand_in_contact: true }],
},
{
name: "Christina",
groups: [
{ name: "client", main_contact: true, stand_in_contact: false },
{ name: "crew", main_contact: false, stand_in_contact: false },
],
},
{
name: "Nina",
groups: [
{ name: "production", main_contact: true, stand_in_contact: false },
],
},
];
CodePudding user response:
Looks like the groups have to be sorted first, then you can sort attendees.
const attendees = [
{
name: "Peter",
groups: [{ name: "agency", main_contact: false, stand_in_contact: true }],
},
{
name: "Alex",
groups: [{ name: "agency", main_contact: true, stand_in_contact: false }],
},
{
name: "Nina",
groups: [
{ name: "production", main_contact: true, stand_in_contact: false },
],
},
{
name: "Christina",
groups: [
{ name: "client", main_contact: true, stand_in_contact: false },
{ name: "crew", main_contact: false, stand_in_contact: false },
],
},
];
const sortOrder = ["agency", "client", "production", "crew"];
const sortAttendees = (attendees, sortOrder) => {
if ([attendees, sortOrder].some(a => !(a instanceof Array))) return;
// first, sort the groups:
attendees.forEach(attendee => attendee.groups.sort((a, b) => sortOrder.indexOf(a.name) - sortOrder.indexOf(b.name) || b.main_contact - a.main_contact));
// now sort attendees:
attendees.sort((a, b) => {
const l = Math.min(a.groups.length, b.groups.length);
for (let i = 0; i < l; i) {
const r = sortOrder.indexOf(a.groups[i].name) - sortOrder.indexOf(b.groups[i].name) || b.groups[i].main_contact - a.groups[i].main_contact;
if (r) return r;
}
return 0;
});
};
sortAttendees(attendees, sortOrder);
console.log( attendees )
.as-console-wrapper {top:0; max-height: 100% !important}
CodePudding user response:
In my solution I give each attendee a rank value based on their highest ranked membership in a group and their main_contact status in that group.
const attendees = [
{
name: "Peter",
groups: [{ name: "agency", main_contact: false, stand_in_contact: true }],
},
{
name: "Alex",
groups: [{ name: "agency", main_contact: true, stand_in_contact: false }],
},
{
name: "Nina",
groups: [
{ name: "production", main_contact: true, stand_in_contact: false },
],
},
{
name: "Christina",
groups: [
{ name: "client", main_contact: true, stand_in_contact: false },
{ name: "crew", main_contact: false, stand_in_contact: false },
],
},
];
const sortAttendees = (attendees) => {
const sortOrder = ["agency", "client", "production", "crew"];
const rank = attendee => attendee.groups
.map(group => sortOrder.indexOf(group.name)*2 1 - group.main_contact)
.sort()
[0];
if (!attendees || attendees.length == 0) return [];
return attendees.sort((a, b) => rank(a)-rank(b));
};
console.log(sortAttendees(attendees));
.as-console-wrapper {top:0; max-height: 100% !important}