5

Why does this code

["Q", "fP", "AQ", "L"].sort((a,b) => a.localeCompare(b))

give this result:

["AQ", "fP", "L", "Q"]

I thought it would give me this (and that's what I need):

["AQ", "L", "Q", "fP"]

All uppercase letters come before lower case letters chortle.ccsu.edu/java5/Notes/chap92/ch92_2.html

Brian Burns
  • 20,575
  • 8
  • 83
  • 77
Rachid O
  • 13,013
  • 15
  • 66
  • 92
  • And why did you think so? It does not make sense. – Adam Orłowski Dec 08 '18 at 23:32
  • 4
    `["Q", "fP", "AQ", "L"].sort()` would give you that output – zer0 Dec 08 '18 at 23:33
  • @AdamOrlov All uppercase letters come before lower case letters https://chortle.ccsu.edu/java5/Notes/chap92/ch92_2.html – Rachid O Dec 08 '18 at 23:36
  • 1
    You would think that `a.localeCompare(b, "en", {sensitivity: 'case', caseFirst: "upper"})` would work ... but it does not. – Akrion Dec 09 '18 at 00:00
  • @RachidOussanaa—that would be the ASCII code sequence order, not lexiographic. The English alphabet is usually presented as AaBbCc and so on, not ABC…abc… – RobG Dec 09 '18 at 00:19
  • @RobG but that's not what lexicographic ordering is http://chortle.ccsu.edu/java5/Notes/chap92/ch92_2.html and https://www.quora.com/What-does-it-mean-by-string-lexicographically-orders-between-two-strings – Rachid O Dec 09 '18 at 00:27
  • 2
    @RachidOussanaa—that definition of lexicographic order is specific to Java and is not in general use. Dictionaries are not ordered with all the words starting with capital letters first, then all the lower case. They've been around for centuries. It just so happens that the ASCII code sequence for alphabetic characters lists the capitals before lower case. *localeCompare* tries to address that. – RobG Dec 09 '18 at 00:36

3 Answers3

4

Don't use localeCompare(), just use sort() directly

let myArray = ["Q", "fP", "AQ", "L"];
myArray.sort();
console.log(myArray);

Interestingly enough, the following works in NodeJS, but not in Browser JavaScript. This is because the ECMAScript standard doesn't dictate which sorting algorithm to use, so it's up the each browser and/or NodeJS to dictate

let myArray = ["Q", "fP", "AQ", "L"];
myArray.sort((a, b) => a > b);
console.log(myArray);

NodeJS Demo

https://repl.it/@AnonymousSB/SO53688028

Documentation

http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.11

AnonymousSB
  • 3,516
  • 10
  • 28
  • 2
    Your last comment doesn't make sense. NodeJS and JavaScript are based on ECMAScript, so there should be zero differences for built-in methods. Both your above snippets sort with "fP" after all the other strings in every browser ECMAScript implementation I tried. Also, `(a, b) => a > b` will not sort consistently as it will return `false` (0) where `a == b` and where `a < b`, rather than 0 and -1 respectively, which is what it should return. – RobG Dec 09 '18 at 00:33
  • If the compare function is undefined, the internal [*sortCompare*](http://ecma-international.org/ecma-262/9.0/#sec-sortcompare) function should be used, which is effectively using `<` and `>` so the [*abstract relational comparison algorithm*](http://ecma-international.org/ecma-262/9.0/#sec-abstract-relational-comparison) is used, which falls back to code units, so not implementation dependent at all. The nodejs demo sorts exactly as browsers do. – RobG Dec 09 '18 at 01:13
  • I don't see that at all. Running the code in your demo sorts as `[ 'AQ', 'L', 'Q', 'Q', 'fP' ]`. The lines in the V8 code implement the sort per ECMA-262 using `<` and `>`, which sorts on code unit, not lexicographically (because ASCII code units aren't in lexicographic order). And surely `\`${a} < ${b}\`, a > b` should be `\`${a} < ${b}\`, a < b`. – RobG Dec 09 '18 at 11:33
  • Because your sort function is broken, as I said earlier. Just sort it as `myArray.sort()` and the result is consistent. You'll get identical results if you fix your sort function as `return a < b? -1 : a > b? 1 : 0;`, which is what the built–in sort function does. – RobG Dec 09 '18 at 11:52
2

Try this:

let myArray = ["Q", "fP", "AQ", "L"];
myArray.sort((a, b) => a > b ? 1 : -1);
console.log(myArray);
0

Don't use localeCompare(), just use sort() directly. As below:

["Q", "fP", "AQ", "L"].sort();
Bimde
  • 722
  • 8
  • 20