2

I have two sorted arrays, and combined them into a new listC.

listA = [
  {id:"1234435", name:"apple", dateTime_ISO:"2019-01-15 17:27:30"},
  {id:"1234435", name:"orange", dateTime_ISO:"2019-01-15 10:25:30"},
  {id:"1234435", name:"banana", dateTime_ISO:"2019-01-15 10:25:02"},
  {id:"1234435", name:"pear", dateTime_ISO:"2019-01-15 07:21:52"},
  {id:"1234435", name:"lemon", dateTime_ISO:"2019-01-15 07:22:24"},
]

listB = [
  {id:"1234435", name:"bread", dateTime:"2019-01-15 17:27:34"},
  {id:"1234435", name:"rice", dateTime:"2019-01-15 09:25:30"},
  {id:"1234435", name:"noodle", dateTime:"2019-01-15 07:25:02"},
  {id:"1234435", name:"pie", dateTime:"2019-01-15 07:06:52"},
  {id:"1234435", name:"cake", dateTime:"2019-01-15 06:22:24"},
]

listC = this.listA.concat(this.listB)

How to sort listC base on the dateTime?

SO I was thinking to get the a new dateTimeList contains only the dateTime, then sort this list, and somehow sort the listC

dateTimeList = this.listA
                .map(x => x.dateTime_ISO)
                .concat(this.listB.map(x => x.dateTime));

But is there any robust way to sort this dateTimeList?

If it cannot be done just because the two lists have different field name (dateTime_ISO and dateTime), then just pretend they are the same. I could modify them to be the same in the database.

Appreciate for any help.

Alex
  • 143
  • 10
  • 1
    Possible duplicate of https://stackoverflow.com/questions/6567941/how-does-sort-function-work-in-javascript-along-with-compare-function; also this question does not seem Angular specific at all, so the title is a bit misleading. – dtanabe Jan 15 '19 at 04:28
  • @dtanabe thanks for the tips, and I will remove the angular tag. – Alex Jan 15 '19 at 04:33

4 Answers4

2

You can take advantage of short circuiting to sort the combined list while still having different properties. For example:

let listA = [{id:"1234435", name:"apple", dateTime_ISO:"2019-01-15 17:27:30"},{id:"1234435", name:"orange", dateTime_ISO:"2019-01-15 10:25:30"},{id:"1234435", name:"banana", dateTime_ISO:"2019-01-15 10:25:02"},{id:"1234435", name:"pear", dateTime_ISO:"2019-01-15 07:21:52"},{id:"1234435", name:"lemon", dateTime_ISO:"2019-01-15 07:22:24"},]
let listB = [{id:"1234435", name:"bread", dateTime:"2019-01-15 17:27:34"},{id:"1234435", name:"rice", dateTime:"2019-01-15 09:25:30"},{id:"1234435", name:"noodle", dateTime:"2019-01-15 07:25:02"},{id:"1234435", name:"pie", dateTime:"2019-01-15 07:06:52"},{id:"1234435", name:"cake", dateTime:"2019-01-15 06:22:24"},]
  
let listC = listA.concat(listB)

listC.sort((a, b) => {
    return (a.dateTime_ISO || a.dateTime).localeCompare((b.dateTime_ISO || b.dateTime))
})
console.log(listC)
Mark
  • 90,562
  • 7
  • 108
  • 148
1

You can use sort(), and in the sort condition check if some property exists (example: dateTime_ISO) and if not use the alternative property name (dateTime):

const listA = [
  {id:"1234435", name:"apple", dateTime_ISO:"2019-01-15 17:27:30"},
  {id:"1234435", name:"orange", dateTime_ISO:"2019-01-15 10:25:30"},
  {id:"1234435", name:"banana", dateTime_ISO:"2019-01-15 10:25:02"},
  {id:"1234435", name:"pear", dateTime_ISO:"2019-01-15 07:21:52"},
  {id:"1234435", name:"lemon", dateTime_ISO:"2019-01-15 07:22:24"},
]

const listB = [
  {id:"1234435", name:"bread", dateTime:"2019-01-15 17:27:34"},
  {id:"1234435", name:"rice", dateTime:"2019-01-15 09:25:30"},
  {id:"1234435", name:"noodle", dateTime:"2019-01-15 07:25:02"},
  {id:"1234435", name:"pie", dateTime:"2019-01-15 07:06:52"},
  {id:"1234435", name:"cake", dateTime:"2019-01-15 06:22:24"},
]

let listC = listA.concat(listB);

// Now, lets sort.

let sortedListC = listC.sort((a, b) =>
{
    let x = (a.dateTime_ISO || a.dateTime);
    let y = (b.dateTime_ISO || b.dateTime);

    return ((x > y) && 1) || ((x < y) && -1) || 0;
});

console.log(sortedListC);
Shidersz
  • 16,846
  • 2
  • 23
  • 48
  • Using a single `>` test in sort is not correct and can lead to incorrect sorts. `sort` expects the function to return `-1`, `1`, or `0` not true or false. Try adding an item with an identical time. – Mark Jan 15 '19 at 05:05
  • I catch what you say, but I tried to generate the problem and I can't. Any ideas why is still working? – Shidersz Jan 15 '19 at 05:19
  • 1
    I think it will often work if it only returns 1 and 0, but it depends on the original order. There’s an old threat here: https://stackoverflow.com/questions/34466125/sort-strings-by-using-less-greater-than-comparison-operators-in-comparator – Mark Jan 15 '19 at 07:45
  • @MarkMeyer thanks for the feedback and help to understand the implicit problem, I have updated to a more robust solution. – Shidersz Jan 15 '19 at 14:47
0

Since listA and listB are already sorted in descending order, I think you can make use of that fact and merge them. This should be O(n) - instead of (nlog(n)) if you sort the result after concatenation.

Try something like this

var listA = [
  {id:"1234435", name:"apple", dateTime_ISO:"2019-01-15 17:27:30"},
  {id:"1234435", name:"orange", dateTime_ISO:"2019-01-15 10:25:30"},
  {id:"1234435", name:"banana", dateTime_ISO:"2019-01-15 10:25:02"},
  {id:"1234435", name:"pear", dateTime_ISO:"2019-01-15 07:21:52"},
  {id:"1234435", name:"lemon", dateTime_ISO:"2019-01-15 07:22:24"},
];

var listB = [
  {id:"1234435", name:"bread", dateTime:"2019-01-15 17:27:34"},
  {id:"1234435", name:"rice", dateTime:"2019-01-15 09:25:30"},
  {id:"1234435", name:"noodle", dateTime:"2019-01-15 07:25:02"},
  {id:"1234435", name:"pie", dateTime:"2019-01-15 07:06:52"},
  {id:"1234435", name:"cake", dateTime:"2019-01-15 06:22:24"},
];

function merge(a, b) {
        var ret = [];
        while (a.length && b.length) {
                var smallest = a[0].dateTime_ISO > b[0].dateTime ? a.shift() : b.shift();
                ret.push(smallest);
        }
        return ret.concat(a.length ? a : b);
};

console.log(JSON.stringify(merge(listA, listB), null, 2));
Khalfella
  • 99
  • 1
  • 1
-1
dateTimeList = this.listA.sort(function(a,b){
      //return a.attributes - b.attributes;
      if(a.date < b.date)
          return 1;
      if(a.date > b.date)
          return -1;
    });

is nice way to sort by date.

Cem Kocagöz
  • 634
  • 12
  • 26