I have an array of objects which I have to loop through and group duplicate values by property name "tagColor", then the grouped objects I need to sort by name. I achieved first step I sorted by color, now I need to sort only those groups by name, implementing this in angular 4, typescript
Here is array list
tags = [
{
"tagType": {
"name": "a",
"tagColor": "#0000FF"
}
},
{
"tagType": {
"name": "a",
"tagColor": "#FF0000"
}
},
{
"tagType": {
"name": "c",
"tagColor": "#FF0000",
}
},
{
"tagType": {
"name": "b",
"tagColor": "#FF0000",
}
},
{
"tagType": {
"name": "b",
"tagColor": "#0000FF",
}
}
]
my function that sorts by tagColor:
tags.sort((a, b) => a.tagType.tagColor.localeCompare(b.tagType.tagColor));
this groups by color only, but how also to sort those groups alphabetically?
I have an array of objects which I have to loop through and group duplicate values by property name "tagColor", then the grouped objects I need to sort by name. I achieved first step I sorted by color, now I need to sort only those groups by name, implementing this in angular 4, typescript
Here is array list
tags = [
{
"tagType": {
"name": "a",
"tagColor": "#0000FF"
}
},
{
"tagType": {
"name": "a",
"tagColor": "#FF0000"
}
},
{
"tagType": {
"name": "c",
"tagColor": "#FF0000",
}
},
{
"tagType": {
"name": "b",
"tagColor": "#FF0000",
}
},
{
"tagType": {
"name": "b",
"tagColor": "#0000FF",
}
}
]
my function that sorts by tagColor:
tags.sort((a, b) => a.tagType.tagColor.localeCompare(b.tagType.tagColor));
this groups by color only, but how also to sort those groups alphabetically?
Share Improve this question edited Jul 31, 2018 at 17:51 AlexFF1 asked Jul 31, 2018 at 17:46 AlexFF1AlexFF1 1,2934 gold badges25 silver badges47 bronze badges 1- You just need a single sort. Color is the primary key, so pare that first. If for two elements the color is the same, then the parison result should be the result of paring secondary keys. – Pointy Commented Jul 31, 2018 at 17:50
3 Answers
Reset to default 7You can use a single sort call, if the result of paring tags is 0 you pare by name:
tags.sort((a, b) => {
let result = b.tagType.tagColor.localeCompare(a.tagType.tagColor);
if(result == 0) {
return a.tagType.name.localeCompare(b.tagType.name);
}
return result;
});
Or a more concise but less readable version:
tags.sort((a, b) =>
b.tagType.tagColor.localeCompare(a.tagType.tagColor) // if this is 0 (aka falsy) return the other value
|| a.tagType.name.localeCompare(b.tagType.name));
Beside the given order by color, you could use a defined custom order for the color with an object which reflects the order.
For colors, not found in the object, you could take a default value to move this colors to a defined position, to the start,
(order[a.tagType.tagColor] || -Infinity) - (order[b.tagType.tagColor] || -Infinity)
to the end,
(order[a.tagType.tagColor] || Infinity) - (order[b.tagType.tagColor] || Infinity)
or inbetween.
(colorOrder[a.tagType.tagColor] || 1.5) - (colorOrder[b.tagType.tagColor] || 1.5)
var tags = [{ tagType: { name: "a", tagColor: "#0000FF" } }, { tagType: { name: "a", tagColor: "#FF0000" } }, { tagType: { name: "c", tagColor: "#FF0000" } }, { tagType: { name: "b", tagColor: "#FF0000" } }, { tagType: { name: "b", tagColor: "#0000FF" } }],
colorOrder = { "#0000FF": 1, "#FF0000": 2 };
tags.sort((a, b) =>
colorOrder[a.tagType.tagColor] - colorOrder[b.tagType.tagColor] ||
a.tagType.name.localeCompare(b.tagType.name)
);
console.log(tags);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Compare by color first and then pare by name in the sort function. The pare function returns -1, 0, 1. If the b should e after the a then the function returns a -1 - no sort needed, if the b is equal to the a the function returns a 0 - no sort needed, if the b needs to e before the a then the function returns a 1 - sort needed. Since -1 and 0 evaluate to false and 1 evaluates to true basically the sort function is returning a true needs to be sorted or false does not need to be sorted. So if you pare by color and it needs to be sorted then we pass the colorSort value, if the color doesn't need to be sorted then we pass the nameSort value
tags.sort((a, b) => {
let colorSort = a.tagType.tagColor.localeCompare(b.tagType.tagColor);
let nameSort = a.tagType.name.localeCompare(b.tagType.name);
return (colorSort)? colorSort:nameSort;
});