16
votes

I'm trying to use JavaScript's localeCompare function for sorting strings.

I was surprised by the results of running the following lines in the devTools console:

"a".localeCompare("b") // returns: -1
"A".localeCompare("b") // returns: -1

Another test:

"b".localeCompare("a") // returns: 1
"B".localeCompare("a") // returns: 1

Even when I am more specific about my sort I get the same result:

"a".localeCompare("b", { usage: "sort", sensitivity: 'variant' }) // -1
"A".localeCompare("b", { usage: "sort", sensitivity: 'variant' }) // -1
"b".localeCompare("a", { usage: "sort", sensitivity: 'variant' }) // 1
"B".localeCompare("a", { usage: "sort", sensitivity: 'variant' }) // 1

I want to use localeCompare to compare strings in a case-sensitive way, so shouldn't "b" compared to "a" and "B" compared to "a" have opposite results?

1
I was going to suggest supplying a locales argument, but, at least with "en" that didn't make a difference. Also tried the "caseFirst" option, but that didn't make a difference either, although it does say Implementations are not required to support this property.Heretic Monkey
Sorry, I don't quite understand your confusion, how would b occur before A in the alphabetic order?Teemu
@Teemu I added another example in my question to show the opposite case...shouldn't "B" be before "a"?Jonathan.Brink
Ehh... No, that would break the alphabetical order. If you need an order, in which all capitals come first, you've to implement your own sort function.Teemu
That might be locale-dependent, afaik a case-sensitive order is AaBbCcDd .... You can switch it to aAbBcCdD using localeCompare though.Teemu

1 Answers

17
votes

LocalCompare can be case-sensitiv, enabled by { sensitivity: 'case'} or the unicode extension: u-kf-upper or u-kf-lower.

The spec of LocalCompare says, that:

The result is intended to order String values in the sort order specified by the system default locale

Or the locale you can add as argument.

The default for en-US for the case sensitive order is "lower" with:

aAbBcC ...

You could change it to "upper", which is:

AaBbCc ...

This test shows that switching from upper to lower does only affect the same letter, and does not sort uppercase-alphabet before lowercase or visa versa.

var b = "A".localeCompare("a", 'en-US-u-kf-lower'); //  1
var c = "A".localeCompare("a", 'en-US-u-kf-upper'); // -1
var d = "A".localeCompare("b", 'en-US-u-kf-upper'); // -1
var e = "A".localeCompare("b", 'en-US-u-kf-lower'); // -1

  • There might be a locale that sorts uppercase/lowercase differently, but I'm not aware of any...
  • the international sort order is case insensitive
  • ASCII sort order would be ACb
  • Some locales have different orders: Finnish for example treads V like W: Va Wb Vc ...

Does case-sensitivity affect numeric values in any way?

var b = "1".localeCompare("a", 'en-US-u-kf-lower'); //  -1
var c = "1".localeCompare("A", 'en-US-u-kf-upper'); // -1
var d = "104".localeCompare("a", 'en-US-u-kf-upper'); // -1

no, but ...

there is an option, how numeric values can be compared: kn

with the option or Unicode extension kn one can enable numeric comparison (kn-true):

var b = "10".localeCompare("2", 'en-US-u-kn-true'); // 1
var c = "10".localeCompare("2", 'en-US'); // -1

However, numbers are always before letters:

var d = "1".localeCompare("a", 'en-US-u-kn-true'); // -1
var e = "1".localeCompare("a", 'en-US'); // -1