0

I have an array of objects that need to be sorted into a list but I'd like to group tied values. The array is essentially:

var sorted = [
    {
        section:"Red",
        score:12
    },
    {
        section:"Green",
        score:12
    },
    {
        section:"Blue",
        score:9
    },
...
]

And the result I am aiming for would be to output something along the lines of Your first choices are Red and Green, your second choice is Blue, your third choices are...

I've sorted the main array already to sort the objects in an ascending order, but don't really know how to address the objects that have the same score.

I have been trying to get this to work https://www.tutorialspoint.com/sort-the-array-and-group-all-the-identical-duplicate-numbers-into-their-separate-subarray-in-javascript but I can't quite figure it out to adapt to my situation. This doesn't quite work but I am getting close. It seems to be missing the first result...

var sorted = [
    {
        section:"Red",
        score:12
    },
    {
        section:"Green",
        score:12
    },
    {
        section:"Blue",
        score:9
    },
    {
        section:"Yellow",
        score:8
    },
    {
        section:"Grey",
        score:6
    },
    {
        section:"Black",
        score:6
    }
]
const sortAndGroup = (sorted = []) => {
   let result = [];
   let groupArray = [];
   for (let i = 1; i < sorted.length; i++) {
      if (sorted[i - 1].score !== sorted[i].score) {
         groupArray = [];
         result.push(groupArray);
      };
      groupArray.push(sorted[i].section + ", " + sorted[i].score);
   };
   return result;
};
console.log(sortAndGroup(sorted));
Stu
  • 327
  • 1
  • 3
  • 14
  • 1
    You forgot to include your attempt at solving this problem. – Scott Hunter Nov 21 '22 at 20:05
  • sorry added what I am working on so far. – Stu Nov 21 '22 at 20:18
  • 1
    First group all the elements by score, then sort this array by score. See https://stackoverflow.com/questions/34523003/group-by-array-and-add-field-and-sub-array-in-main-array for the grouping part. – Barmar Nov 21 '22 at 21:00

1 Answers1

1

Using reduce() we can combine the grouping with the sorting.

If we use the number score as index of our result array from reduce(), we only need to remove the undefined's from the array to end up with a sorted list of objects

var data = [
    { section:"Blue",   score:9  },
    { section:"Yellow", score:8  }, 
    { section:"Red",    score:12 },
    { section:"Purple", score: 1 },
    { section:"Green",  score:12 },
    { section:"Grey",   score:6  },
    { section:"Black",  score:6  }
]

let result = data.reduce((a, c) => {
    if (!a[c.score]) a[c.score] = { score: c.score, options: [ ]};
    a[c.score].options.push(c.section)
    return a
}, []).filter(Boolean);

result.forEach(({ score, options }, i) => {
    console.log(`${i + 1} --> Score: ${score}\tOptions: ${options.join(', ')}`); 
});
1 --> Score: 1  Options: Purple
2 --> Score: 6  Options: Grey, Black
3 --> Score: 8  Options: Yellow
4 --> Score: 9  Options: Blue
5 --> Score: 12 Options: Red, Green
0stone0
  • 34,288
  • 4
  • 39
  • 64
  • I've had some great success with this so far. I am now trying to reverse the order as I am trying to have it ascending... is there a way to do that with reduce? – Stu Nov 21 '22 at 22:39
  • 1
    If I understand you correctly, add a `.reverse()` behind `.filter(Boolean)`. (On mobile now, otherwise I'd add a snippet ;) ) – 0stone0 Nov 21 '22 at 22:44
  • 1
    AMAZING. Oh man I was struggling with this. Thank you so much. I'm off to read more about .reduce but I've got it working now and can continue on! Really appreciate the help. – Stu Nov 21 '22 at 22:46