简体   繁体   中英

How can I sort an array of objects by 3 fields with conditions and null values always come last

I have an array of objectds and need to sort by 3 date fields (date1, date2, date3)

  1. fist sort by date1 ascending
  2. if there are more docs with same date1 sort by date3 ascending
  3. (docs with null or undefined date1 must be last)
  4. if date1 is undefined or null sort by date2 ascending,
  5. if there are more docs with same date2 sort by date3 ascending

Lets say I have this array:


    [
        { date1: null, date2: '20120-01-08', date3: '20120-01-06' },
        { date1: null, date2: '20120-01-09', date3: '20120-01-05' },
        { date1: null, date2: '20120-01-08', date3: '20120-01-05' },
        { date1: '20120-01-05', date2: '20120-01-07', date3: '20120-01-01' },
        { date1: '20120-01-04', date2: '20120-01-07', date3: '20120-01-02' },
        { date1: '20120-01-04', date2: '20120-01-10', date3: '20120-01-01' }
    ]

i need to get this:


    [
        { date1: '20120-01-04', date2: '20120-01-10', date3: '20120-01-01' },
        { date1: '20120-01-04', date2: '20120-01-07', date3: '20120-01-02' },
        { date1: '20120-01-05', date2: '20120-01-07', date3: '20120-01-01' },
        { date1: null, date2: '20120-01-08', date3: '20120-01-05' },
        { date1: null, date2: '20120-01-08', date3: '20120-01-06' },
        { date1: null, date2: '20120-01-09', date3: '20120-01-05' }
    ]

I tried using array.sort() and managed to solve the fitst 3 requirements:

  1. fist sort by date1 ascending
  2. if there are more docs with same date1 sort by date3 ascending
  3. (docs with null or undefined date1 must be last)

using this sort function:


    var array = [
      { date2: "20120-01-08", date3: "20120-01-06" },
      { date2: "20120-01-09", date3: "20120-01-05" },
      { date2: "20120-01-08", date3: "20120-01-05" },
      { date1: "20120-01-05", date2: "20120-01-07", date3: "20120-01-01" },
      { date1: "20120-01-04", date2: "20120-01-07", date3: "20120-01-02" },
      { date1: "20120-01-04", date2: "20120-01-10", date3: "20120-01-01" }
    ];

    var result = array.sort(function(obj1, obj2) {
      if (!obj1.date1 || !obj2.date1) {
        return -1;
      } else {
        if (obj1.date1 > obj2.date1) return 1;
        if (obj1.date1 < obj2.date1) return -1;
        if (obj1.data3 > obj2.data3) return 1;
        if (obj1.date3 < obj2.date3) return -1;
        return 0;
      }
    });

I get this:


    0: {date1: "20120-01-04", date2: "20120-01-10", date3: "20120-01-01"}
    1: {date1: "20120-01-04", date2: "20120-01-07", date3: "20120-01-02"}
    2: {date1: "20120-01-05", date2: "20120-01-07", date3: "20120-01-01"}
    3: {date2: "20120-01-08", date3: "20120-01-05"}
    4: {date2: "20120-01-09", date3: "20120-01-05"}
    5: {date2: "20120-01-08", date3: "20120-01-06"}

I'm not sure how to solve those 2:

  1. if date1 is undefined or null sort by date2 ascending,
  2. if there are more docs with same date2 sort by date3 ascending

the records with undefined date1 are not sorted...

https://codepen.io/wyzix33/pen/agaKRp

Thanks

You could sort by

  • undefined / null / falsy values of date1 and sort them to bottom,
  • date1 or if falsy date2 ,
  • date3 .

 var data = [{ date1: null, date2: '20120-01-08', date3: '20120-01-06' }, { date1: null, date2: '20120-01-09', date3: '20120-01-05' }, { date1: null, date2: '20120-01-08', date3: '20120-01-05' }, { date1: '20120-01-05', date2: '20120-01-07', date3: '20120-01-01' }, { date1: '20120-01-04', date2: '20120-01-07', date3: '20120-01-02' }, { date1: '20120-01-04', date2: '20120-01-10', date3: '20120-01-01' }]; data.sort((a, b) => !a.date1 - !b.date1 || (a.date1 || a.date2).localeCompare(b.date1 || b.date2) || a.date3.localeCompare(b.date3) ); console.log(data); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

I used a little hacking, but unfortunately it took a long time to execute! To set the undefined and null to the largest date in limit, then computed value of per item and do compare!

var array = [{
    date1: null,
    date2: "20120-01-08",
    date3: "20120-01-06"
}, {
    date1: null,
    date2: "20120-01-08",
    date3: "20120-01-05"
}, {
    date1: null,
    date2: "20120-01-09",
    date3: "20120-01-05"
},
{
    date1: "20120-01-05",
    date2: "20120-01-07",
    date3: "20120-01-01"
}, {
    date1: "20120-01-04",
    date2: "20120-01-05",
    date3: "20120-01-02"
},
{
    date1: "20120-01-04",
    date2: "20120-01-07",
    date3: "20120-01-01"
}];

var result = array.sort(function(obj1, obj2) {

    var copyObj1 = {...obj1},copyObj2 ={...obj2};
    var largestDate = '20121-12-31'

    copyObj1.date1 = copyObj1.date1 || largestDate
    copyObj2.date1 = copyObj2.date1 || largestDate

    var value1 = Object.values(copyObj1).join('')
    var value2 = Object.values(copyObj2).join('')
    return value1.localeCompare(value2)
})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM