1

Sorting an array behaves differently in Browser and Node.js environment when the comparator function returns boolean value instead of number.

e.g.

var x =  [
        {
            "id": 1110000003977716,
            "updatedAt": 1558353055000,
        },
        {
            "id": 1,
            "updatedAt": 1551783874000,
        },
        {
            "id": 2,
            "updatedAt": 1551788206000,
        },
        {
            "id": 3,
            "updatedAt": 1552066859000,
        },
        {
            "id": 4,
            "updatedAt": 1552578810000,
        },
        {
            "id": 5,
            "updatedAt": 1552598063000,
        },
        {
            "id": 6,
            "updatedAt": 1554906497000,
        },
        {
            "id": 7,
            "updatedAt": 1555061487000,
        },
        {
            "id": 8,
            "updatedAt": 1555357728000,
        },
        {
            "id": 9,
            "updatedAt": 1555616572000,
        },
        {
            "id": 10,
            "updatedAt": 1555698720000,
        },
        {
            "id": 11,
            "updatedAt": 1555843111000,
        },
        {
            "id": 12,
            "updatedAt": 1555851294000,
        },
        {
            "id": 13,
            "updatedAt": 1557408493000,

        }
    ];

and sorting method

x.sort((p, n) => p.updatedAt < n.updatedAt)

Browser sort this array correctly,

Output

 [
   {
      "id":1110000003977716,
      "updatedAt":1558353055000
   },
   {
      "id":13,
      "updatedAt":1557408493000
   },
   {
      "id":12,
      "updatedAt":1555851294000
   },
   {
      "id":11,
      "updatedAt":1555843111000
   },
   {
      "id":10,
      "updatedAt":1555698720000
   },
   {
      "id":9,
      "updatedAt":1555616572000
   },
   {
      "id":8,
      "updatedAt":1555357728000
   },
   {
      "id":7,
      "updatedAt":1555061487000
   },
   {
      "id":6,
      "updatedAt":1554906497000
   },
   {
      "id":5,
      "updatedAt":1552598063000
   },
   {
      "id":4,
      "updatedAt":1552578810000
   },
   {
      "id":3,
      "updatedAt":1552066859000
   },
   {
      "id":2,
      "updatedAt":1551788206000
   },
   {
      "id":1,
      "updatedAt":1551783874000
   }
]

But in node.js the result is different (sometimes correct);

Output

[
   {
      "id":7,
      "updatedAt":1555061487000
   },
   {
      "id":1110000003977716,
      "updatedAt":1558353055000
   },
   {
      "id":8,
      "updatedAt":1555357728000
   },
   {
      "id":13,
      "updatedAt":1557408493000
   },
   {
      "id":12,
      "updatedAt":1555851294000
   },
   {
      "id":11,
      "updatedAt":1555843111000
   },
   {
      "id":10,
      "updatedAt":1555698720000
   },
   {
      "id":9,
      "updatedAt":1555616572000
   },
   {
      "id":6,
      "updatedAt":1554906497000
   },
   {
      "id":5,
      "updatedAt":1552598063000
   },
   {
      "id":4,
      "updatedAt":1552578810000
   },
   {
      "id":3,
      "updatedAt":1552066859000
   },
   {
      "id":2,
      "updatedAt":1551788206000
   },
   {
      "id":1,
      "updatedAt":1551783874000
   }
]

Please explain why this behaviour is different in these two engines.

P.S. I have tested my code in Chrome and Firefox.

Minkesh Jain
  • 1,140
  • 1
  • 10
  • 24
  • you witness the different implementations of `sort`. please have a look to the above link. – Nina Scholz Jun 03 '19 at 11:19
  • When the boolean outcome is `false`, the sorting algorithm considers the values to be *equal* in their ordering (a 0 return value means "equal"). Depending on the sorting algorithm this may result in those two values being relatively ordered in either way. – trincot Jun 03 '19 at 11:22
  • 1
    `n.vale` is potentially undefined, thus the whole expression is not valid – Eriks Klotins Jun 03 '19 at 11:23
  • The core of the problem is that booleans can confuse things if `compare(a, b)` returns `false`, then the two are *equal* and thus you logically don't need to check `compare(b, a)` which would otherwise say they aren't. – VLAZ Jun 03 '19 at 11:24
  • Not what you asked, but the correct way to sort numeric-ish values using array sort is by returning the DIFFERENCE between each pair, like this: `x.sort((p, n) => p.val - n.val);` – Pedro Lima Jun 03 '19 at 11:24
  • @EriksKlotins thanks for pointing out, updating the question. – Minkesh Jain Jun 03 '19 at 11:55
  • @VLAZ I don't think it's a duplicate as you have mentioned it, My question is why there is different implementation of sort function in Node.js and Browser. – Minkesh Jain Jun 04 '19 at 06:07
  • @MinkeshJain and the answer there goes in detail. There is no standard for what sorting algorithm is to be used, so the JS environment can use any it prefers. It even differs between browsers and between the number of items you try to sort. Bottom line is that *you* aren't being compliant with the sorting interface, hence you get the inaccuracies – VLAZ Jun 04 '19 at 06:42
  • @VLAZ it could be same answer but it is not a duplicate question, you can post the link of the answer here but remove the duplicate tag. – Minkesh Jain Jun 04 '19 at 08:22
  • You return a boolean in the comparison callback to sorting. The dupe is about returning booleans in the comparison during sorting. It goes into a great detail answering *exactly* what you are after. You are focusing on the difference between Node.js and the browser, while the dupe is more generic and focusing on anything and everything that can go wrong when you have the same base problem as yours. – VLAZ Jun 04 '19 at 08:30
  • No necessarily, I am more focussed on why the implementation is different in both these environments and shouldn't there be an standardization in place, I would rather want to have answers for that than why returning boolean gives different results. – Minkesh Jain Jun 04 '19 at 09:09
  • Why should there be a single sorting algorithm across all places? The *standard* says that `.sort` should sort stuff according to the result of the comparison function or, if none provided, it should do a lexicographic sort. Any implementation that does this should be valid. Freedom in implementation means there there is more room for optimisation - e.g., low amounts of data might simply be bubble-sorted - it has a higher big-O factor but lower static costs. Large amounts of data might be quicksorted or heapsorted. The environment might be better for one but not the other. – VLAZ Jun 04 '19 at 10:39
  • See, you are showering all new information here. Just remove the duplicate tag already since the context of the question is entirely different. – Minkesh Jain Jun 04 '19 at 11:08

0 Answers0