2

An algorithm that I am implementing requires to sort an array in reverse lexical ordering. However, after discovering some incorrect results I found that this line is causing some trouble:

someArray.slice().sort((a, b) => b - a);

Further investigations show that the above is not equivalent to the following statement:

someArray.slice().sort().reverse();

For example,

var someArray = ["11", "2", "1"];
someArray.slice().sort().reverse();       // ["2", "11", "1"]
someArray.slice().sort((a, b) => b - a);  // ["11", "2", "1"]

The problem with .sort((a, b) => b - a) is that b - a is casting the values to numbers, as thus not sorting by the correct lexical ordering.

Currently my solution is to do b.localeCompare(a), but that assumes both a and b contain only "English" characters in order for the two statements to be equivalent.

An obvious but ugly solution is this:

someArray.slice().sort((a, b) => a < b ? 1 : a > b ? -1 : 0);

but this seems very long and unnecessary. Is there a better way to sort an array in reverse lexical order?

Derek 朕會功夫
  • 92,235
  • 44
  • 185
  • 247
  • 1
    It doesn't seem ugly for me, at all. – kind user Apr 14 '17 at 09:33
  • @Aaron Performance is a nice thing to have since it might be used to deal with large datasets. After reading the linked question most probably I would be using the nested ternary operator solution or `(a < b) - (b > a)`, given that `.localeCompare` might have significant performance impact on certain browsers. – Derek 朕會功夫 Apr 14 '17 at 09:43
  • Given your reputation, I think you already figured out my solution, but could you tell me why this is bad ? someArray.slice().sort((a, b) => b.toString() - a.toString()); – Logar Apr 14 '17 at 09:47
  • @Logar `b.toString() - a.toString()` suffers the same problem, and in this case both `a` and `b` are casted to strings and then back to numbers. – Derek 朕會功夫 Apr 14 '17 at 09:49
  • Lol right, thanks. I should at least test it next time – Logar Apr 14 '17 at 09:52
  • FYI: *"...I would be using the nested ternary operator solution or `(a < b) - (b > a)`"* I assume that's a typo, the `a` and `b` need to be in the same order on both sides of that. BTW, on performance: https://jsperf.com/string-sorting-with-relational-operators Looks like `a == b ? 0 : a < b : -1 : 1` is best on Firefox and IE11, either that or `a < b -1 ? a > b ? 1 : 0` on Chrome, and the coercing version (`(a < b) - (a > b)`) is slowest on all. Don't have Edge handy. :-) – T.J. Crowder Apr 14 '17 at 10:14
  • 1
    @T.J.Crowder Ah thanks that's indeed a typo :) Also thank you for the performance comparisons. – Derek 朕會功夫 Apr 14 '17 at 10:16

0 Answers0