0

My data set is grouped by "event" and "region":

groupedData: Array(14)
0: [{…}]
1: (3) [{…}, {…}, {…}]
2: [{…}]
3: [{…}]
4: Array(3)
    0: {id: 326, event: "SUPPORT", region: "X", …}
    1: {id: 397, event: "SUPPORT", region: "X", …}
    2: {id: 298, event: "SUPPORT", region: "X", …}
    length: 3
    __proto__: Array(0)
5: (2) [{…}, {…}]
6: (9) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
7: Array(5)
    0: {id: 483, event: "COVID", region: "IV", …}
    1: {id: 448, event: "COVID", region: "IV", …}
    2: {id: 549, event: "COVID", region: "IV", …}
    3: {id: 600, event: "COVID", region: "IV", …}
    4: {id: 634, event: "COVID", region: "IV", …}
    length: 5
    __proto__: Array(0)
8: Array(4)
    0: {id: 118, event: "COVID", region: "IX", …}
    1: {id: 922, event: "COVID", region: "IX", …}
    2: {id: 959, event: "COVID", region: "IX", …}
    3: {id: 856, event: "COVID", region: "IX", …}
    length: 4
    __proto__: Array(0)
9: Array(1)
    0: {id: 747, event: "COVID", region: "V", …}
    length: 1
    __proto__: Array(0)
10: (5) [{…}, {…}, {…}, {…}, {…}]
11: (3) [{…}, {…}, {…}]
12: (6) [{…}, {…}, {…}, {…}, {…}, {…}]
13: (6) [{…}, {…}, {…}, {…}, {…}, {…}]
length: 14

As you can see the problem is with "region IX" because it is sorting ASC. There are many converters/functions to convert Roman Numerals to numbers for comparisons, so I am not too concerned about that.

What has me puzzled is how to use splice or slice to move the region IX array, wherever it may occur, to a position before the "X" array (if there is one) or after the "VIII" array (or whatever becomes before it if there is none), but still under the same "event"? Also, can this be accomplished without looping?

Utilizing JavaScript, jQuery and in ES5 only.

Kevin
  • 17
  • 5

2 Answers2

0

To sort an array we must visit each element once. The sort() array method sorts the array in place using a provided sorting function.

The elements within groupData are arrays, but we don't need to iterate these sub-arrays because the objects all have the same region. We just need to look at the region of the first element of the sub-array when comparing.

function sortByNumeral(item1, item2) {
    var num1 = romanNumeralToInt(item1[0].region)
    var num2 = romanNumeralToInt(item2[0].region)
    return (num1 - num2)
}
groupedData.sort(sortByNumeral)

Of course you will need to define romanNumeralToInt on your own.

EDIT: To achieve the order specified in your comment (event first, then region) the following sort function should work

function sortData(item1, item2) {
    var event1 = item1[0].event
    var event2 = item2[0].event
    if (event1 < event2) {
        return -1
    } else if (event1 > event2) {
        return 1
    } else { // events are equal, so sort by numeral
        var num1 = romanNumeralToInt(item1[0].region)
        var num2 = romanNumeralToInt(item2[0].region)
        return (num1 - num2)
    }
}
Moarram
  • 66
  • 4
  • Close (IX is in the right place) but now I get ... ` Event B Region I Event A Region II Event B Region III Event C Region IV Event B Region V ' What I need is (sorted by Event, Then Region within each Event).... ' Event A Region II Event B Region I Event B Region III Event B Region V Event C Region IV ` – Kevin Jul 29 '20 at 21:51
0

@Moarram put me on the right track (can't uptick cause my rep is too low), but I used @SnowBurnts answer from How to sort an array of objects by multiple fields?...

homes.sort(
   function(a, b) {          
      if (a.city === b.city) {
         // Price is only important when cities are the same
         return b.price - a.price;
      }
      return a.city > b.city ? 1 : -1;
   });

...with Roman Numeral to number convertor also from Stackoverflow (although I do not remember the link)...

function romanToArabic(romanNumber){
          romanNumber = romanNumber.toUpperCase();
          const romanNumList = ["CM","M","CD","D","XC","C","XL","L","IX","X","IV","V","I"];
          const corresp = [900,1000,400,500,90,100,40,50,9,10,4,5,1];
          let index =  0, num = 0;
          for(let rn in romanNumList){
            index = romanNumber.indexOf(romanNumList[rn]);
            while(index != -1){
              num += parseInt(corresp[rn]);
              romanNumber = romanNumber.replace(romanNumList[rn],"-");
              index = romanNumber.indexOf(romanNumList[rn]);
            }
          }
          return num;
        }

...To come up with this code that keeps the Events together while sorting the Regions within each Event...

var sortedByEventRegion = groupedData.sort(
                       function(a, b) {          
                          if (a[0].event === b[0].event) {
                             // Region is only important when Events are the same
                             return romanToArabic(b[0].region) - romanToArabic(a[0].region);
                          }
                          return a[0].event > b[0].event ? 1 : -1;
                       });
Kevin
  • 17
  • 5