Hacker News new | ask | show | jobs
by 52-6F-62 2838 days ago
It depends on whether or not you pass it a basic comparator function, eg:

    someArray.sort((a,b) => a - b);
But yeah the example would have needed this for the less complex example as well to be accurate.
2 comments

Common mistake when writing a sorting function, a-b is not safe in languages with integer overflow because it will give you incorrect sorting for large numbers. In javascript where everything is double you're probably safe from that kind of error but maybe NaN can give you problems instead?
Too true.

‘a-b’ is safe enough in JS if you always know the input will be within a safe range regarding integer sizes and types.

NaN can give you all kinds of trouble so I’d usually test for that in a real case, either before the sort or in the comparator—if necessary.

Shouldn't that be `a < b`?
No, the compare function needs to be able to indicate when two values are equal, not just when one is smaller/larger than the other. Otherwise your sort function will return inconsistent results for compare(a, b) and compare(b, a) when both values are equal.
So

    someList.sort((a,b) => a => b)
Would be better, because it produces a stable sort?

`a - b` produces the same results, so equally valid?

(I'm assuming you meant "a >= b", not "a => b".)

That's still not a consistent comparison function, so the results are implementation-defined.

To be consistent, it's required, among others, that if cmp(a, b) == 0 then cmp(b, a) == 0. For "a >= b", this is not always true, e.g.:

  » cmp(0, 1) == 0
  true
  » cmp(1, 0) == 0
  false
No. `(a,b) => a => b` cannot produce a stable sort in all scenarios. Would theoretically work fine for integers since there's no difference between any two instances of the same number, but consider:

  let arr = [
    {number: 2, name: 'a'},
    {number: 1, name: 'b'},
    {number: 1, name: 'c'},
  ]
Now assume we want to sort arr with a compare function, and our sort function expects the compare function to return a boolean, not an integer.

    let compare = (a,b) => a.number => b.number
    compare(arr[0], arr[1]) //=> true, so the object named 'a' comes after 'b'
    compare(arr[1], arr[2]) //=> true, so the object named 'b' comes after 'c'?
See the problem?
That will give you a sequence of decreasing numbers. `a-b` will work just as `a > b`.

If `a-b` returns a negative number, the result will be treated as -1. If the numbers are the same, then you end up with 0, and so on.

I don't know what's faster in that case.

a > b is not a consistent comparison function. The behavior of sort() with such a function is implementation-defined.
Agreed. I wouldn't use it the way shown here. I would make sure to return a hard negative, zero, or one in any case.

I was surprised when I read into how many different ways `Array.prototype.sort()` is implemented across environments.