Hacker News new | ask | show | jobs
by alyandon 2839 days ago
Sort example doesn't take into account Javascript does lexicographical sorting?

javascript:

  someList = [ 40, 2, 1, 3, 7, 99]
  someList.sort()
  Array(6) [ 1, 2, 3, 40, 7, 99 ]
python:

  someList = [ 40, 2, 1, 3, 7, 99]
  sorted(someList)
  [1, 2, 3, 7, 40, 99]
6 comments

Your comment led me to discover https://www.reddit.com/r/softwaregore and reaffirm myself that I should stay away from javascript for as long as I can
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.
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.

Oh gosh. TIL.

Edit: I'm actually truly grateful, I'm sure this bit of knowledge saved me some of my hair in the future.

To me this seems like a bug, or at best an incomplete implementation. Let's fix it in the next version of JavaScript, okay? I suppose someone's code will break, but was it worth preserving?
That's a good point. Although there is another sorting example which is using the correct format. But yes, you are indeed right.
I swear this language gets worse every time I learn something new about it.