【问题标题】:localeCompare returns 0 for different unicode symbolslocaleCompare 为不同的 unicode 符号返回 0
【发布时间】:2020-07-21 23:23:58
【问题描述】:

我希望使用localeCompare 对字符串进行严格排序,但我发现它返回0,当给定两个不同的unicode 字符时,错误地表明它们是相同的,例如

ℜ U+211C (alt-08476) BLACK-LETTER CAPITAL R = 实部

ℝ U+211D (alt-08477) DOUBLE-STRUCK CAPITAL R = 实数集

"ℜ".localeCompare("ℝ", "en")   
> 0

"ℜ" === "ℝ"                    
> false

"ℜ".charCodeAt(0)
> 8476

"ℝ".charCodeAt(0)
> 8477

我查看了文档,但默认值已经用于“排序”和“变体”,这似乎是最严格的可用:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Collator/Collator

localeCompare 不能给严格的命令吗?

【问题讨论】:

    标签: javascript string string-comparison


    【解决方案1】:

    似乎String.localeCompare()在检测到它们都是大写字母R的非ASCII版本后,正确地指出这两个字符的顺序没有特别的区别。

    console.log(
      // two non-0x43 uppercase Cs
      'ℂ'.localeCompare('?', 'en'),
    
      // two non-0x5A uppercase Zs
      "ℤ".localeCompare('?', 'en'),
      
      // 0x5A ASCII Z precedes both:
      "Z".localeCompare('ℤ', 'en'),
      "Z".localeCompare('?', 'en'),
    );

    您可以在由于规范等价而没有定义排序顺序的地方使用 unicode 位置:

    const sort = (a, b) => a.localeCompare(b) || -(a < b);
    
    console.log(
      //  1 (C < ? in localeCompare)
      sort('?', 'C'),
      // -1 (Canonically equivalent; falls back to 0x2102 < 0xD835)
      sort('ℂ', '?')  
    );

    来自ECMAScript spec

    实际返回值由实现定义以允许 实现者在值中编码附加信息,但是 需要函数来定义所有字符串的总排序并 比较被Unicode标准视为canonically equivalent的字符串时返回0

    来自关于 Unicode 等价的维基百科文章:

    Unicode 提供了两个这样的概念,规范等价和 兼容性。规范定义的代码点序列 假定等效项具有相同的外观和含义 打印或显示。

    例如,代码点 U+006E(拉丁文 小写n)后跟U+0303(组合波浪号◌̃)是 由 Unicode 定义为规范地等效于单个代码 点 U+00F1(西班牙字母表的小写字母 ñ)。

    因此,这些序列应该以相同的方式显示, 应通过应用程序以相同的方式处理,例如 按字母顺序排列名称或搜索,并且可以替换每个 其他。类似地,每个被编码为 单个字符可以等效地编码为一个组合 前导连词jamo,元音连词jamo,如果合适的话, 尾随连体jamo。

    另请参阅:https://unicode.org/reports/tr10/

    【讨论】:

    • @JonasWilms 好链接,已添加!
    猜你喜欢
    • 1970-01-01
    • 2023-03-09
    • 2012-02-05
    • 1970-01-01
    • 1970-01-01
    • 2012-02-07
    • 1970-01-01
    • 2018-01-21
    相关资源
    最近更新 更多