将JavaScript字符串拆分为代码点数组?(考虑到"代理对"而不是"字形群")

hip*_*ail 15 javascript string unicode codepoint surrogate-pairs

将JavaScript字符串拆分为"字符"可以简单地完成,但如果您关心Unicode(并且您应该关心Unicode)则会出现问题.

JavaScript本身将字符视为16位实体(UCS-2或UTF-16),但这不允许BMP(基本多语言平面)之外的Unicode字符.

为了处理BMP之外的Unicode字符,JavaScript必须考虑" 代理对 ",它本身并不是这样做的.

我正在寻找如何通过codepoint拆分js字符串,无论代码点是否需要一个或两个JavaScript"字符"(代码单元).

根据您的需要,按代码点拆分可能还不够,您可能希望拆分" 字形集群 ",其中集群是基本代码点,后跟所有非间距修改代码点,例如组合重音符号和变音符号.

出于这个问题的目的,我不需要通过字形集群进行拆分.

Joh*_*zer 17

@ bobince的答案(幸运的是)变得有点过时了; 你现在可以简单地使用了

var chars = Array.from( text )
Run Code Online (Sandbox Code Playgroud)

获取一个单一代码点字符串列表,它遵循星体/ 32位/代理Unicode字符.


Bre*_*mir 7

沿着@John Frazer 的回答,可以使用这种更简洁的字符串迭代形式:

const chars = [...text]
Run Code Online (Sandbox Code Playgroud)

例如,与:

const text = 'A\uD835\uDC68B\uD835\uDC69C\uD835\uDC6A'
const chars = [...text] // ["A", "", "B", "", "C", ""]
Run Code Online (Sandbox Code Playgroud)


bob*_*nce 5

在 ECMAScript 6 中,您将能够使用字符串作为迭代器来获取代码点,或者您可以在字符串中搜索/./ug,或者您可以getCodePointAt(i)重复调用。

\n\n

不幸的是for..of语法和正则表达式标志不能被polyfilled并且调用polyfilledgetCodePoint()会非常慢(O(n\xc2\xb2)),所以我们暂时还不能真正使用这种方法。

\n\n

因此,以手动方式进行:

\n\n
String.prototype.toCodePoints= function() {\n    chars = [];\n    for (var i= 0; i<this.length; i++) {\n        var c1= this.charCodeAt(i);\n        if (c1>=0xD800 && c1<0xDC00 && i+1<this.length) {\n            var c2= this.charCodeAt(i+1);\n            if (c2>=0xDC00 && c2<0xE000) {\n                chars.push(0x10000 + ((c1-0xD800)<<10) + (c2-0xDC00));\n                i++;\n                continue;\n            }\n        }\n        chars.push(c1);\n    }\n    return chars;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

对于与此相反的内容,请参阅/sf/answers/263151031/

\n

  • `getCodePointAt` 是 `O(n)`。它接受的参数不是代码点索引,而是代码单元索引(常规字符串索引)。 (4认同)