2

I am now working in javascript string sorting using localeCompare and my data will contain several null values too.

And i found a weird behavior with localeCompare when comparing string and null value. When comparing string value upto startswith a/A to n/N it working fine as below.

"n".localeCompare(null) // return -1;
"N".localeCompare(null) // return -1;

But after if i compare the null value with o/O to z/Z it returns 1

"o".localeCompare(null) // return 1;
"O".localeCompare(null) // return 1;

I know that localeCompare work with comparing Unicode but why the above behavior happens is there any reason?

Madhu
  • 2,416
  • 3
  • 15
  • 33

3 Answers3

5

localeCompare compares strings, as such anything passed to it will be converted to a string, and you'll get the same result from

"n".localeCompare("null") // return -1;
"o".localeCompare("null") // return 1;

because

The localeCompare() method returns a number indicating whether a reference string comes before or after or is the same as the given string in sort order.

MDN

which means

"null".localeCompare("null") -> will return 0 as it's the same string
"n".localeCompare("null") -> will return -1 as it comes before null "o".localeCompare("null") -> will return 1 as it comes after null

adeneo
  • 312,895
  • 29
  • 395
  • 388
  • Thanks for you reply. You mean the `null` is converted into string when passed as argument to the `localeCompare` and so should i handle it outside?? – Madhu Mar 17 '15 at 13:24
  • `localeCompare` **only** compares strings, so yes anything passed to it will be treated as a string, and null isn't a string and can't really be compared to `n`. How you handle that, depends on what you're expecting when comparing strings and `null` ? – adeneo Mar 17 '15 at 13:26
  • Thanks it explains lot, i am going to mark this as answer. – Madhu Mar 17 '15 at 13:35
0

If you want a real-world comparer that can handle null values

Then, you are better off implementing something like this,

function stringComparer(a,b) {
  if(a && b)
    return a.localeCompare(b);
  else 
    // sort null and "" to bottom
    if(a)
      return -1;
    else if(b)
      return 1;
    else 
      return 0;
}

and using it to compare your values. Here is an example,

['Łove','Love',null,"",null,'kellogs','Kellogs','kellogs',null,"Lover","   ",'Man',"abc", "AAb", "Abc"].sort(stringComparer)

There is some room for improving this depending on how you want null, " " and "" values to sort in relation to each other. In the above implementation, " " will sort to the top while null and "" values will sort to the bottom.

Shyam Habarakada
  • 15,367
  • 3
  • 36
  • 47
0

According to MDN:

"All values are coerced to strings, so omitting it or passing undefined causes localeCompare() to compare against the string "undefined", which is rarely what you want."

So it's literally comparing the string "null".

You unfortunately need to check for undefined values and handle them. And you can't just check for 1 or -1 because:

Warning: Do not rely on exact return values of -1 or 1! Negative and positive integer results vary between browsers (as well as between browser versions) because the ECMAScript specification only mandates negative and positive values. Some browsers may return -2 or 2, or even some other negative or positive value.

You will want to grab the value live to confirm. For example:

let basicCompare = "a".localeCompare("b");

Then code to compare two strings A and B:

if (!A && B) {
  return -(basicCompare);
}

You would need another condition for if A && !B, an initial one if both A && B exist. And a final fourth for if both don't exist.

Nate Levin
  • 918
  • 9
  • 22
N.Hubbard
  • 1
  • 1