Sorting an array based on multiple values

Viewed 69

I am trying to sort the below array, based on multiple values, report_yr and report_qtr, the array should be sorted according to year first and then as per quarter(for that same year).

// input array

let arr = [{
  report_yr: '2008',
  report_qtr: '1'
},
{
  report_yr: '2019',
  report_qtr: '3'
},
{
  report_yr: '2019',
  report_qtr: '4'
},
{
  report_yr: '2017',
  report_qtr: '2'
},
{ report_yr: '2008',
  report_qtr: '2'
}];

// expected output:

[ 
{ report_yr: '2019',
report_qtr: '4' },
{ report_yr: '2019',
report_qtr: '3' },
{ report_yr: '2008',
report_qtr: '1'
},{ report_yr: '2008',
report_qtr: '2'
},
{ report_yr: '2017',
report_qtr: '2' } ];

// What I am trying:

I am trying to use loadash methods for this,

_.sortBy(arr,
      ['report_yr', 'report_qtr']);

Similarly tried with orderBy but no luck so far.

5 Answers

You can use sort method and do this with plain javascript.

let arr = [{"report_yr":"2008","report_qtr":"1"},{"report_yr":"2019","report_qtr":"3"},{"report_yr":"2019","report_qtr":"4"},{"report_yr":"2017","report_qtr":"2"},{"report_yr":"2008","report_qtr":"2"}]

arr.sort((a, b) => b.report_yr - a.report_yr || b.report_qtr - a.report_qtr)
console.log(arr)

This may be work for you.

data.sort(function (x, y) {
    var n = y.report_qtr - x.report_qtr;
    if (n !== 0) {
        return n;
    }

    return y.report_yr- x.report_yr;
});

Use sort method

let arr = [{
  report_yr: '2008',
  report_qtr: '1'
},
{
  report_yr: '2019',
  report_qtr: '3'
},
{
  report_yr: '2019',
  report_qtr: '4'
},
{
  report_yr: '2017',
  report_qtr: '2'
},
{ report_yr: '2008',
  report_qtr: '2'
}]

arr.sort((b, a) => +a.report_yr - +b.report_yr || +a.report_qtr - +b.report_qtr )

console.log(arr)

what If you add report_yr + report_qtr and sort descending like this

    arr = arr.sort((a, b) => {
        const one = parseInt(a.report_yr) + parseInt(a.report_qtr);
        const two = parseInt(b.report_yr) + parseInt(b.report_qtr);
        if (one > two) {
            return -1
        }
        return 1;
    });

Use _.orderBy instead of _.sortBy. If you do not, you cannot sort descending.

This will sort the report_qtr descending and report_yr ascending. I noticed your desired output contradicts sorting though...

let arr = [{
  report_yr: '2008',
  report_qtr: '1'
}, {
  report_yr: '2019',
  report_qtr: '3'
}, {
  report_yr: '2019',
  report_qtr: '4'
}, {
  report_yr: '2017',
  report_qtr: '2'
}, {
  report_yr: '2008',
  report_qtr: '2'
}];

let sortedArr = _.orderBy(arr, ['report_qtr', 'report_yr'], ['desc', 'asc']);

console.log(sortedArr);
.as-console-wrapper {
  top: 0;
  max-height: 100% !important;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>


If you really want that order, you can do this:

  1. Find the year frequency
  2. Sort by frequency
  3. Sort by year
  4. Check if the years are odd, sort by quarter descending
  5. Check if the years are even, sort by quarter ascending
  6. Fall back to sorting by quarter ascending

let arr = [
  { report_yr: '2008', report_qtr: '1' },
  { report_yr: '2019', report_qtr: '3' },
  { report_yr: '2019', report_qtr: '4' },
  { report_yr: '2017', report_qtr: '2' },
  { report_yr: '2008', report_qtr: '2' }
];

const yearFreq = arr.reduce((o, i) => ({...o, [i.report_yr] : (o[i.report_yr] || 0) + 1}), {});

let sortedArray = arr.sort((a, b) => {
  let diff = yearFreq[b.report_yr] - yearFreq[a.report_yr];
  if (diff !== 0) return diff;
  let a_year = parseInt(a.report_yr, 10);
  let b_year = parseInt(b.report_yr, 10);
  diff = b_year - a_year;
  if (diff !== 0) return diff;
  let a_odd = a_year % 2 === 1;
  let b_odd = b_year % 2 === 1;
  let a_qtr = parseInt(a.report_qtr, 10);
  let b_qtr = parseInt(b.report_qtr, 10);
  if (a_odd && b_odd) return b_qtr - a_qtr;
  if (!a_odd && !b_odd) return a_qtr - b_qtr;
  return a_qtr - b_qtr;
});

console.log(sortedArray);
.as-console-wrapper { top: 0; max-height: 100% !important; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>

<!-- Expected

[{
  "report_yr": "2019",
  "report_qtr": "4"
}, {
  "report_yr": "2019",
  "report_qtr": "3"
}, {
  "report_yr": "2008",
  "report_qtr": "1"
}, {
  "report_yr": "2008",
  "report_qtr": "2"
}, {
  "report_yr": "2017",
  "report_qtr": "2"
}]

-->

Related