3

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?

enter image description here

1
  • You just need a single sort. Color is the primary key, so compare that first. If for two elements the color is the same, then the comparison result should be the result of comparing secondary keys. Commented Jul 31, 2018 at 17:50

3 Answers 3

7

You can use a single sort call, if the result of comparing tags is 0 you compare 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));
Sign up to request clarification or add additional context in comments.

3 Comments

thanks its exactly doing the job, how you practice those things I am not too long in development? thanks for answer, going learn this
@AlexFF1 Not sure I get the question, do you mean how I knew how to do it.. not sure .. after a while it mostly just comes to you :)
thanks I understand, its more you practice the more natural it becomes, thanks
2

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; }

Comments

1

Compare by color first and then compare by name in the sort function. The compare function returns -1, 0, 1. If the b should come 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 come 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 compare 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;
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.