【问题标题】:How to sort strings in JavaScript by code point values?如何按代码点值对 JavaScript 中的字符串进行排序?
【发布时间】:2022-01-05 03:24:26
【问题描述】:

我需要对一个字符串数组进行排序,其中元素按字典顺序作为代码点值序列进行比较,例如,"Z" < "a" < "\udabc" < "�" < "????"

  1. 除了手动迭代两个字符串并比较相应的代码点之外,还有更有效的比较字符串的方法吗?
  2. 如果保证字符串没有任何代理代码点(但可能有代理对,所以"�" < "????" 应该仍然成立)怎么办?对于这种特殊情况,是否有更有效的程序?

注意:StackOverflow 上有很多解释如何对字符串进行排序的答案,但它们要么使用localeCompare 顺序,要么使用 JavaScript 比较运算符定义的顺序(将字符串作为 UTF-16 代码单元的序列进行比较)。我对这两个都不感兴趣。

【问题讨论】:

  • 如何使用charCodeAt 将它们转换为数字并按此排序?
  • @evolutionxbox 字符串可以是任意长度,单字符串仅作为示例。
  • 我想知道是否有办法将Unicode Codepoint Collation 用于Intl 比较函数

标签: javascript unicode comparison codepoint


【解决方案1】:

如何在 JavaScript 中按代码点值对字符串进行排序?


这似乎是一个令人惊讶的难题。这是一个概念证明 (POC) 实现:

'use strict';

function compareCodePoints(s1, s2) {
    const len = Math.min(s1.length, s2.length);
    let i = 0;
    for (const c1 of s1) {
        if (i >= len) {
            break;
        }
        const cp1 = s1.codePointAt(i);
        const cp2 = s2.codePointAt(i);
        const order = cp1 - cp2;
        if (order !== 0) {
            return order;
        }
        i++;
        if (cp1 > 0xFFFF) {
            i++;
        }
    }
    return s1.length - s2.length;
}

let s =[];
let s1 = "abc?z";
let s2 = "abc?z";

s = [s1, s2];
console.log(s);
s.sort(compareCodePoints);
console.log(s);

console.log()

s = [s2, s1];
console.log(s);
s.sort(compareCodePoints);
console.log(s);

console.log()

s1 = "a";
s2 = "";

console.log([s1, s2]);
console.log(compareCodePoints(s1, s2));
console.log([s2, s1]);
console.log(compareCodePoints(s2, s1));

$ node codepoint.poc.js
[ 'abc?z', 'abc?z' ]
[ 'abc?z', 'abc?z' ]

[ 'abc?z', 'abc?z' ]
[ 'abc?z', 'abc?z' ]

[ 'a', '' ]
1
[ '', 'a' ]
-1
$

【讨论】:

  • 您的代码是 for (const c1 of s1),但 c1 没有在任何地方使用。此外,compareCodePoints("a", "") 返回 NaN,Array.sort 将其视为 0。
  • @abacabadabacaba:我已经修复了NaN 错误。这是一个 POC,因此可能存在其他极端情况。 for (const c1 of s1) 构造用于确保对 UTF-16 的正确迭代。
  • OP 要求“除了手动迭代它们并比较相应的代码点
  • @Bergi:OP 问题标题,“如何在 JavaScript 中按代码点值对字符串进行排序?”有关按代码点值对 JavaScript 中的字符串进行排序的示例,请参阅我的答案。一个完整的OP问题,“除了手动迭代它们并比较相应的代码点之外,还有更有效的比较字符串的方法吗?”答案是不。详情请参阅Unicode Standard
猜你喜欢
  • 1970-01-01
  • 2019-08-02
  • 2017-07-13
  • 1970-01-01
  • 2014-10-28
  • 2010-09-08
  • 1970-01-01
  • 2016-12-05
相关资源
最近更新 更多