javascriptstring-comparison

Force localeCompare to be case-sensitive


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?


Solution

  • 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
    


    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