0

I've got an array of objects each containing a momentjs object datestamp which I thought would be trivial to sort by. For some reason, it is returning inaccurate sorting:

const sortedArray = [...merged].sort((a, b) => (a.txDate.isAfter(b.txDate)));

What I get is this:

[ { txDate: moment("2018-02-14T00:00:00.000"), id: 45 },
  { txDate: moment("2017-12-31T00:00:00.000"), id: 0 },
  { txDate: moment("2018-02-15T00:00:00.000"), id: 46 },
  { txDate: moment("2018-01-02T00:00:00.000"), id: 2 },
  { txDate: moment("2018-01-01T00:00:00.000"), id: 1 },
  { txDate: moment("2018-02-17T00:00:00.000"), id: 48 },
  ...
]

Clearly, this is not sorted chronologically by txDate.

I tried isolating the problem by taking a few of these incorrectly sorted objects and trying the same algorithm on a smaller sample size:

const mergedSample = [merged[0], merged[45], merged[46], merged[51], merged[52], merged[58], merged[49], merged[40], merged[80], merged[37]]
const sortedArraySample = [...mergedSample].sort((a, b) => (a.txDate.isAfter(b.txDate)));

and for some reason this works.

[ { txDate: moment("2017-12-31T00:00:00.000"), id: 0 },
  { txDate: moment("2018-02-06T00:00:00.000"), id: 37 },
  { txDate: moment("2018-02-09T00:00:00.000"), id: 40 },
  { txDate: moment("2018-02-14T00:00:00.000"), id: 45 },
  { txDate: moment("2018-02-15T00:00:00.000"), id: 46 },
  { txDate: moment("2018-02-18T00:00:00.000"), id: 49 },
  { txDate: moment("2018-02-20T00:00:00.000"), id: 51 },
  { txDate: moment("2018-02-21T00:00:00.000"), id: 52 },
  { txDate: moment("2018-02-27T00:00:00.000"), id: 58 },
  { txDate: moment("2018-03-21T00:00:00.000"), id: 80 } ]

I thought maybe this was a memory issue and the sort was behaving strangely under larger loads, but the full 'merged' array is only length ~90, so I feel it's safe to presume that's not the case. After hours of toiling with this, I'm out of guesses. Thoughts?

DrLove
  • 51
  • 1
  • 9

1 Answers1

0

Array.prototype.sort takes in a function that returns an integer (0, < 0, > 0) based on the comparison. Moment.isAfter returns a boolean, so your sort function is working by chance in your test case, and it can vary depending on the browser implementation.

Moments can make use of +/- operators and your sort function can be:

const sortedArray = [...merged].sort((a, b) => a.txDate - b.txDate);

Look at Sorting in JavaScript: Shouldn't returning a boolean be enough for a comparison function? for detailed explanations.

clouddreams
  • 622
  • 1
  • 4
  • 13