20

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?

Jonathan.Brink
  • 23,757
  • 20
  • 73
  • 115
  • 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 Jan 18 '16 at 18:38
  • Sorry, I don't quite understand your confusion, how would `b` occur before `A` in the alphabetic order? – Teemu Jan 18 '16 at 18:40
  • @Teemu I added another example in my question to show the opposite case...shouldn't "B" be before "a"? – Jonathan.Brink Jan 18 '16 at 18:55
  • 2
    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 Jan 18 '16 at 19:05
  • @Teemu ok so perhaps that is my confusion...I was thinking that the case-sensitive order would be ABCD...abcd.. Is that not correct? – Jonathan.Brink Jan 18 '16 at 19:08
  • 1
    That might be locale-dependent, afaik a case-sensitive order is `AaBbCcDd ...`. You can switch it to `aAbBcCdD` using `localeCompare` though. – Teemu Jan 18 '16 at 19:16

1 Answers1

18

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
jHilscher
  • 1,810
  • 2
  • 25
  • 29
  • Any idea how to sort numbers after strings? like `"109".localCompare('a')` – Vadorequest Feb 14 '17 at 10:07
  • @Vadorequest No, I don't think that's possible with localCompare. – jHilscher Apr 10 '17 at 19:26
  • Hi, I am trying sort on this array = [{name:"Acuityads"},{name:"alpha"}];. And I want alpha first. array.sort(function(a,b){return a.name.localeCompare(b.name, 'en-US'); })); it is returning Acuityads first. I am trying to achieve aAbBcC – Rashmi Jan 22 '21 at 09:39