1

I have an array of Objects that contains the fYear and FQtr keys. My goal is to sort by FQtr keys and fYear. Would you please help?

Original Data

const data = [
    { "fYear": "FY22 Q3", "FQtr": "W10"},
    { "fYear": "FY22 Q3", "FQtr": "W11"},
    { "fYear": "FY22 Q3", "FQtr": "W12"},
    { "fYear": "FY22 Q3", "FQtr": "W13"},
    { "fYear": "FY22 Q3", "FQtr": "W2"},
    { "fYear": "FY22 Q4", "FQtr": "W1"},
    { "fYear": "FY22 Q3", "FQtr": "W3"},
    { "fYear": "FY22 Q3", "FQtr": "W4"},
    { "fYear": "FY22 Q4", "FQtr": "W2"},
    { "fYear": "FY22 Q3", "FQtr": "W5"},
    { "fYear": "FY22 Q3", "FQtr": "W6"},
    { "fYear": "FY22 Q3", "FQtr": "W7"},
    { "fYear": "FY22 Q3", "FQtr": "W8"},
    { "fYear": "FY22 Q3", "FQtr": "W9"},
    { "fYear": "FY22 Q4", "FQtr": "W4"},
    { "fYear": "QTD", "FQtr": "QTD"},
    { "fYear": "FY22 Q4", "FQtr": "W3"}
]

Expected Sorted Data


const data = [
    { "fYear": "FY22 Q3", "FQtr": "W2"},
    { "fYear": "FY22 Q3", "FQtr": "W3"},
    { "fYear": "FY22 Q3", "FQtr": "W4"},
    { "fYear": "FY22 Q3", "FQtr": "W5"},
    { "fYear": "FY22 Q3", "FQtr": "W6"},
    { "fYear": "FY22 Q3", "FQtr": "W7"},
    { "fYear": "FY22 Q3", "FQtr": "W8"},
    { "fYear": "FY22 Q3", "FQtr": "W9"},
    { "fYear": "FY22 Q3", "FQtr": "W10"},
    { "fYear": "FY22 Q3", "FQtr": "W11"},
    { "fYear": "FY22 Q3", "FQtr": "W12"},
    { "fYear": "FY22 Q3", "FQtr": "W13"},
    { "fYear": "FY22 Q4", "FQtr": "W1"},
    { "fYear": "FY22 Q4", "FQtr": "W2"},
    { "fYear": "FY22 Q4", "FQtr": "W3"},
    { "fYear": "FY22 Q4", "FQtr": "W4"},
    { "fYear": "QTD", "FQtr": "QTD"}
]

My Approach

function sortFQtr( a, b ) {
    const [prevVal, nextVal] = [Number.parseInt(a.FQtr.substring(1)), Number.parseInt(b.FQtr.substring(1))];
  if ( prevVal < nextVal ) return -1;
  if ( prevVal > nextVal) return 1;
  return 0;
}

// ["FY22 Q4", "FY22 Q3", "QTD"]
 var fYears = data.map(value => value.fYear).filter( (value, index, _arr) => _arr.indexOf(value) == index);

Jeff
  • 380
  • 7
  • 20
  • You don't need to convert the `fYear` parts to integer. If those are not equal, you can do a string compare. The `FQtr` is harder because there are digits, but you have most of the code in place. – Tim Roberts Jul 26 '22 at 22:48
  • 1
    Will you need to parse the data at some point or will you just use the strings everywhere? If you are going to parse the strings anyway, then you can use your parsing functions to guide your sorting algorithm. If not, then using [`String.prototype.localeCompare()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare) is the simplest approach. – jsejcksn Jul 26 '22 at 22:59

1 Answers1

3

Put everything inside the .sort callback. While you're comparing the FQtrs properly, you also need to factor in the fYear values in the same function.

localeCompare will make this easy - lexiographically, FY22 Q3 is followed by FY22 Q4, which is then followed by QTD. Sort by that difference - and if there is no difference, then sort by the FQtr property, which can also be done with localeCompare (with the numeric option).

const data = [
    { "fYear": "FY22 Q3", "FQtr": "W10"},
    { "fYear": "FY22 Q3", "FQtr": "W11"},
    { "fYear": "FY22 Q3", "FQtr": "W12"},
    { "fYear": "FY22 Q3", "FQtr": "W13"},
    { "fYear": "FY22 Q3", "FQtr": "W2"},
    { "fYear": "FY22 Q4", "FQtr": "W1"},
    { "fYear": "FY22 Q3", "FQtr": "W3"},
    { "fYear": "FY22 Q3", "FQtr": "W4"},
    { "fYear": "FY22 Q4", "FQtr": "W2"},
    { "fYear": "FY22 Q3", "FQtr": "W5"},
    { "fYear": "FY22 Q3", "FQtr": "W6"},
    { "fYear": "FY22 Q3", "FQtr": "W7"},
    { "fYear": "FY22 Q3", "FQtr": "W8"},
    { "fYear": "FY22 Q3", "FQtr": "W9"},
    { "fYear": "FY22 Q4", "FQtr": "W4"},
    { "fYear": "QTD", "FQtr": "QTD"},
    { "fYear": "FY22 Q4", "FQtr": "W3"}
];

data.sort((a, b) => (
  a.fYear.localeCompare(b.fYear)
  || a.FQtr.localeCompare(b.FQtr, 'en', { numeric: true })
));
console.log(data);
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320