1

In React, I have an array of objects with an createdAt attribute which I'm trying to sort on. However the sort doesn't seem to work properly because some it comes out in the wrong order. I've written the following code in Node.js for testing... any help would be appreciated.

const moment = require('./node_modules/moment/moment.js')

const sortObjects = () => {
  const objects = [
    {id: "cje633i3v03wl0130lsse3zev", createdAt: "2018-02-27T20:07:49.000Z"},
    {id: "cjeqtudhd000u0149skzacpq5", createdAt: "2018-03-14T08:31:57.000Z"},
    {id: "cje633goc03vn01309m2iocas", createdAt: "2018-02-27T20:07:48.000Z"},
    {id: "cje633k1z03ww0130ce27niez", createdAt: "2018-02-27T20:07:52.000Z"},
    {id: "cje633k3303x50130n1a7vnft", createdAt: "2018-02-27T20:07:52.000Z"},
    {id: "cje633k5b03xa0130m07ndgpn", createdAt: "2018-02-27T20:07:52.000Z"},
    {id: "cje633k2y03x10130q1076pq4", createdAt: "2018-02-27T20:07:52.000Z"},
    {id: "cje633k0b03wq0130bmg0t6rd", createdAt: "2018-02-27T20:07:52.000Z"},
    {id: "cje633gmp03ve0130xu314ti4", createdAt: "2018-02-27T20:07:47.000Z"},
    {id: "cje633i2x03wd0130cqk5sdap", createdAt: "2018-02-27T20:07:49.000Z"},
    {id: "cje633i1w03w60130rfpngz0b", createdAt: "2018-02-27T20:07:49.000Z"},
    {id: "cje633i1u03w301307s44jfyy", createdAt: "2018-02-27T20:07:49.000Z"},
    {id: "cje633i3i03wh0130f3t1iyl4", createdAt: "2018-02-27T20:07:49.000Z"},
    {id: "cje633gp803vw0130frck18wq", createdAt: "2018-02-27T20:07:48.000Z"},
    {id: "cje633gos03vs0130tzv7xfpe", createdAt: "2018-02-27T20:07:48.000Z"},
    {id: "cje633gnu03vj0130nnt4abin", createdAt: "2018-02-27T20:07:47.000Z"},
    {id: "cje633enx03uo0130qw0r35l6", createdAt: "2018-02-27T20:07:45.000Z"},
    {id: "cje633eot03uw0130r42aqbox", createdAt: "2018-02-27T20:07:45.000Z"},
    {id: "cje633eou03uy0130hdwg0uvn", createdAt: "2018-02-27T20:07:45.000Z"},
    {id: "cje633epl03v30130hsugr6vp", createdAt: "2018-02-27T20:07:45.000Z"},
    {id: "cje633eps03v70130xr826vf2", createdAt: "2018-02-27T20:07:45.000Z"},
  ]
  objects.sort( (a, b) => moment.utc(b.createdAt).isAfter(moment.utc(a.createdAt)));
  console.log('objects',objects)
}

sortObjects()

Update - here's the output

[ { id: 'cje633i1w03w60130rfpngz0b', createdAt: '2018-02-27T20:07:49.000Z' },
   { id: 'cje633i3v03wl0130lsse3zev', createdAt: '2018-02-27T20:07:49.000Z' },
   { id: 'cje633i3i03wh0130f3t1iyl4', createdAt: '2018-02-27T20:07:49.000Z' },
   { id: 'cje633k1z03ww0130ce27niez', createdAt: '2018-02-27T20:07:52.000Z' },
   { id: 'cje633k3303x50130n1a7vnft', createdAt: '2018-02-27T20:07:52.000Z' },
   { id: 'cje633k5b03xa0130m07ndgpn', createdAt: '2018-02-27T20:07:52.000Z' },
   { id: 'cje633k2y03x10130q1076pq4', createdAt: '2018-02-27T20:07:52.000Z' },
   { id: 'cje633k0b03wq0130bmg0t6rd', createdAt: '2018-02-27T20:07:52.000Z' },
   { id: 'cje633i1u03w301307s44jfyy', createdAt: '2018-02-27T20:07:49.000Z' },
   { id: 'cje633i2x03wd0130cqk5sdap', createdAt: '2018-02-27T20:07:49.000Z' },
   { id: 'cjeqtudhd000u0149skzacpq5', createdAt: '2018-03-14T08:31:57.000Z' },
   { id: 'cje633goc03vn01309m2iocas', createdAt: '2018-02-27T20:07:48.000Z' },
   { id: 'cje633gp803vw0130frck18wq', createdAt: '2018-02-27T20:07:48.000Z' },
   { id: 'cje633gos03vs0130tzv7xfpe', createdAt: '2018-02-27T20:07:48.000Z' },
   { id: 'cje633gmp03ve0130xu314ti4', createdAt: '2018-02-27T20:07:47.000Z' },
   { id: 'cje633gnu03vj0130nnt4abin', createdAt: '2018-02-27T20:07:47.000Z' },
   { id: 'cje633enx03uo0130qw0r35l6', createdAt: '2018-02-27T20:07:45.000Z' },
   { id: 'cje633eot03uw0130r42aqbox', createdAt: '2018-02-27T20:07:45.000Z' },
   { id: 'cje633eou03uy0130hdwg0uvn', createdAt: '2018-02-27T20:07:45.000Z' },
   { id: 'cje633epl03v30130hsugr6vp', createdAt: '2018-02-27T20:07:45.000Z' },
   { id: 'cje633eps03v70130xr826vf2', createdAt: '2018-02-27T20:07:45.000Z' } ]
Blackstone4
  • 681
  • 1
  • 9
  • 21

5 Answers5

3

You are returning true or false from the sort callback when you should return a number. Aside from that you don't need moment.js to sort by those dates. You can just use:

objects.sort( (a, b) => new Date(a.createdAt) - new Date(b.createdAt));

to sort in ascending order, or flip a and b to sort in descending order.

Paul
  • 139,544
  • 27
  • 275
  • 264
1

You could treat the ISO 8601 date strings as stings. They are sortable without using date methods, as long as they are un thge same time zone (which is actually zulu (UTC)).

const objects = [{ id: "cje633i3v03wl0130lsse3zev", createdAt: "2018-02-27T20:07:49.000Z" }, { id: "cjeqtudhd000u0149skzacpq5", createdAt: "2018-03-14T08:31:57.000Z" }, { id: "cje633goc03vn01309m2iocas", createdAt: "2018-02-27T20:07:48.000Z" }, { id: "cje633k1z03ww0130ce27niez", createdAt: "2018-02-27T20:07:52.000Z" }, { id: "cje633k3303x50130n1a7vnft", createdAt: "2018-02-27T20:07:52.000Z" }, { id: "cje633k5b03xa0130m07ndgpn", createdAt: "2018-02-27T20:07:52.000Z" }, { id: "cje633k2y03x10130q1076pq4", createdAt: "2018-02-27T20:07:52.000Z" }, { id: "cje633k0b03wq0130bmg0t6rd", createdAt: "2018-02-27T20:07:52.000Z" }, { id: "cje633gmp03ve0130xu314ti4", createdAt: "2018-02-27T20:07:47.000Z" }, { id: "cje633i2x03wd0130cqk5sdap", createdAt: "2018-02-27T20:07:49.000Z" }, { id: "cje633i1w03w60130rfpngz0b", createdAt: "2018-02-27T20:07:49.000Z" }, { id: "cje633i1u03w301307s44jfyy", createdAt: "2018-02-27T20:07:49.000Z" }, { id: "cje633i3i03wh0130f3t1iyl4", createdAt: "2018-02-27T20:07:49.000Z" }, { id: "cje633gp803vw0130frck18wq", createdAt: "2018-02-27T20:07:48.000Z" }, { id: "cje633gos03vs0130tzv7xfpe", createdAt: "2018-02-27T20:07:48.000Z" }, { id: "cje633gnu03vj0130nnt4abin", createdAt: "2018-02-27T20:07:47.000Z" }, { id: "cje633enx03uo0130qw0r35l6", createdAt: "2018-02-27T20:07:45.000Z" }, { id: "cje633eot03uw0130r42aqbox", createdAt: "2018-02-27T20:07:45.000Z" }, { id: "cje633eou03uy0130hdwg0uvn", createdAt: "2018-02-27T20:07:45.000Z" }, { id: "cje633epl03v30130hsugr6vp", createdAt: "2018-02-27T20:07:45.000Z" }, { id: "cje633eps03v70130xr826vf2", createdAt: "2018-02-27T20:07:45.000Z" }];

objects.sort((a, b) => b.createdAt.localeCompare(a.createdAt));
  
console.log(objects);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • *Assuming they are all using the same timezone, which they indeed do appear to be from the OP's question. – Paul Mar 15 '18 at 17:43
0
var sortedObj = objects.sort(function(a,b){
    return new Date(b.createdAt) - new Date(a.createdAt);
});

console.log(sortedObj)
Sagar Jajoriya
  • 2,377
  • 1
  • 9
  • 17
0

Compare them as strings. a.createdAt < b.createdAt? 1 : -1 will sort descending. a.createdAt > b.createdAt? 1 : -1 sill sort ascendant

const sortObjects = () => {
  const objects = [
    {id: "cje633i3v03wl0130lsse3zev", createdAt: "2018-02-27T20:07:49.000Z"},
    {id: "cjeqtudhd000u0149skzacpq5", createdAt: "2018-03-14T08:31:57.000Z"},
    {id: "cje633goc03vn01309m2iocas", createdAt: "2018-02-27T20:07:48.000Z"},
    {id: "cje633k1z03ww0130ce27niez", createdAt: "2018-02-27T20:07:52.000Z"},
    {id: "cje633k3303x50130n1a7vnft", createdAt: "2018-02-27T20:07:52.000Z"},
    {id: "cje633k5b03xa0130m07ndgpn", createdAt: "2018-02-27T20:07:52.000Z"},
    {id: "cje633k2y03x10130q1076pq4", createdAt: "2018-02-27T20:07:52.000Z"},
    {id: "cje633k0b03wq0130bmg0t6rd", createdAt: "2018-02-27T20:07:52.000Z"},
    {id: "cje633gmp03ve0130xu314ti4", createdAt: "2018-02-27T20:07:47.000Z"},
    {id: "cje633i2x03wd0130cqk5sdap", createdAt: "2018-02-27T20:07:49.000Z"},
    {id: "cje633i1w03w60130rfpngz0b", createdAt: "2018-02-27T20:07:49.000Z"},
    {id: "cje633i1u03w301307s44jfyy", createdAt: "2018-02-27T20:07:49.000Z"},
    {id: "cje633i3i03wh0130f3t1iyl4", createdAt: "2018-02-27T20:07:49.000Z"},
    {id: "cje633gp803vw0130frck18wq", createdAt: "2018-02-27T20:07:48.000Z"},
    {id: "cje633gos03vs0130tzv7xfpe", createdAt: "2018-02-27T20:07:48.000Z"},
    {id: "cje633gnu03vj0130nnt4abin", createdAt: "2018-02-27T20:07:47.000Z"},
    {id: "cje633enx03uo0130qw0r35l6", createdAt: "2018-02-27T20:07:45.000Z"},
    {id: "cje633eot03uw0130r42aqbox", createdAt: "2018-02-27T20:07:45.000Z"},
    {id: "cje633eou03uy0130hdwg0uvn", createdAt: "2018-02-27T20:07:45.000Z"},
    {id: "cje633epl03v30130hsugr6vp", createdAt: "2018-02-27T20:07:45.000Z"},
    {id: "cje633eps03v70130xr826vf2", createdAt: "2018-02-27T20:07:45.000Z"},
  ]
  objects.sort( (a, b) =>a.createdAt < b.createdAt? 1 : -1);
  console.log('objects',objects)
}

sortObjects()
0

I can confirm to you that, due the unstable sort algorithm used by Javascript you have to return 3 possible values: 1,0 and -1. The sort order for elements with the same value is not guarantee. So a correct sort function call could be (in pure JavaScript)

var a = [{key:2},{key:1},{key:2},{key:3}]
//sort in ascending order
a = a.sort((a,b)=>{ 
    return (a<b) ? -1 : ((a>b) ? 1 : 0)
});
MadPapo
  • 495
  • 4
  • 13