1

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

1
  • Generally these “how do I sort my array” questions are pretty bad, so let me commend you on a decent, non-trivial sorting question with a good amount of code you’ve tried yourself. Commented Jul 6, 2019 at 7:10

2 Answers 2

2

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; }

Sign up to request clarification or add additional context in comments.

6 Comments

Perfect! Thank you!
when date1 was equal, then date2 compare aren't execute, Do you see the "date2": "20120-01-10", and "date2": "20120-01-07",
@Phil.hsu, i don't get you.
@NinaScholz { "date1": "20120-01-04", "date2": "20120-01-10", "date3": "20120-01-01" }, and { "date1": "20120-01-04", "date2": "20120-01-07", "date3": "20120-01-02" }, who will be the first one?
date2 is not compared, only if date1 is not available. in this case date1 and date3 is used for comparing. see point 4 of op.
|
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)
})

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.