3

I have an array of objects I want to apply a custom sorting to in my Angular Project.

A simple example of what I want to achieve is each object has the properties id and category.

let cars: { id: number, category: string }[] = [ { "id": 3, "category": "fast car" }, { "id": 0, "category": "fast car" }, { "id": 1, "category": "slow car" }, { "id": 2, "category": "fast car" } ]; 

No, I want to sort the Array. First, every Fast Car should appear (if there are multiple sorts by id), then Slow car (if there are multiple sort by id as well).

{ "id": 0, "category": "fast car" } { "id": 2, "category": "fast car" } { "id": 3, "category": "fast car" } { "id": 1, "category": "slow car" } 

I don't really get how the .sort function works. Since I am new to programming a rather detailed description of how to use .sort() in this case would be helpful.

    4 Answers 4

    2

    Explanation: Since you asked for a description, I'm trying my best to explain it as simple as possible first: The sort function you apply to an array generally expects two arguments to be compared directly and returns a number. This number can be seen as "smaller than" (negative), "greater than" (positive) or "equals" (zero). Therefore, the function will be called multiple times in your case. In theory, it's also possible to not have these two arguments, e.g. for a random order you could write: cars.sort(() => Math.random() - 0.5)

    So, any function that returns a number can be used in order to sort an array. In your case it would be:

    Sorting by defined hierachy of categories / use ID in case of same category:

    const cars: { id: number; category: string }[] = [ { id: 3, category: "fast car" }, { id: 0, category: "fast car" }, { id: 1, category: "slow car" }, { id: 2, category: "fast car" } ]; const orderCategory = { 'fast car': 1, 'slow car': 2 }; cars.sort((carA, carB) => { if (carA.category !== carB.category) { return orderCategory[carA.category] - orderCategory[carB.category]; } else { return carA.id - carB.id; } }); console.log(cars); 

    Two other advices:

    • You can use const instead of let in your case
    • You do not have to use quotation marks for id and category

    I hope my explanation could help you! Happy coding


    EDIT: Formatted code.


    EDIT 2: I just saw that you wanted fast cars to be listed at first. In my previous implementation, this worked because of the alphabetical order (F < S). But if the alphabetical order is not the reason why you want them to be listed at first, you'll have to define categories. You could now rename "fast car" to "sports car" (everywhere) and the respective cars would be listed at first, whereas they would have been below each "slow car" based on the alphabetical sorting.

    I just updated the code above. This is the old implementation based on the alphabetical order:

    Alphabetical sorting of categories / use ID in case of same category:

    cars.sort((carA, carB) => { if (carA.category < carB.category) { return -1; } else if (carA.category > carB.category) { return 1; } // same as: else if (carA.category === carB.category) else { return carA.id - carB.id; } }); 

    EDIT 3: Adjusted random sorting example in my explanation. Math.random() returns a number between 0 and 1. Thus, I substracted 0.5 in order to randomly return a negative number.

    3
    • You're welcome, I'm glad that I could help. Thanks for accepting this answer!
      – LucasL
      CommentedNov 19, 2019 at 12:03
    • @DocBenchpress I just edited my answer since it might not have been exactly what you asked for. Please check it out and feel free to contact me in case of further questions.
      – LucasL
      CommentedNov 20, 2019 at 11:17
    • Yeah I realized that the order is caused by the alphabetical comparison. In combination with "StepUp"'s approach i managed to create an appropriate solution. Thank you for the correctionsCommentedNov 20, 2019 at 12:12
    1

    It is possible to create own rules to sort and then just use sort function of vanilla JavaScript:

    let array = [ { "id": 3, "category": "fast car" }, { "id": 0, "category": "fast car" }, { "id": 1, "category": "slow car" }, { "id": 2, "category": "fast car" } ] let order = { 'fast car': 1, 'slow car': 2}; array.sort(function (a, b) { return order[a.category] - order[b.category]; }); console.log(array);

      1

      1) Use to display First every Fast Car

      var orders = ["fast car","slow car"]; 

      2) Use to display First every slow Car

      var orders = ["slow car","fast car"]; 

      3) Array of Objects

      var cars = [ { "id": 3, "category": "fast car" }, { "id": 0, "category": "fast car" }, { "id": 1, "category": "slow car" }, { "id": 2, "category": "fast car" } ] 

      4) Logic should be

      var sortedArray = cars.sort(function(a,b) { return (orders.indexOf(a.category)) - (orders.indexOf(b.category)); }); console.log(sortedArray); 
        1

        You can pass a custom compare function to array's sort method:

        cars.sort((a, b) => { // your custom logic here. 'a' stands for first item, 'b' - for second item and so on // the implementation can be like: if (a.category.startsWith('fast') && b.category.startsWith('slow')) { return 1; // 1 means positive number indicating that a > b } else if (a.category.startsWith('slow') && b.category.startsWith('fast') { return -1; // -1 - a negative number indicating a < b } else { // this block will be executed if both categories are 'slow' or 'fast' return a.id - b.id; // we are subtracting IDs to receive some number, either negative or positive. Depending on what number is returned the elements will be either replaced or not. } }) 

          Start asking to get answers

          Find the answer to your question by asking.

          Ask question

          Explore related questions

          See similar questions with these tags.