如何在 JavaScript 中将 Unicode 字符串拆分为字符

Gin*_*den 12 javascript unicode

很长一段时间,我们使用幼稚的方法在 JS 中拆分字符串:

someString.split('');
Run Code Online (Sandbox Code Playgroud)

但是表情符号的流行迫使我们改变这种方法——表情符号字符(和其他非 BMP 字符)像由两个“字符”组成。

String.fromCodePoint(128514).split(''); // array of 2 characters; can't embed due to StackOverflow limitations
Run Code Online (Sandbox Code Playgroud)

那么什么是现代、正确和高效的方法来完成这项任务呢?

Omk*_*r76 12

在数组文字中使用展开:

const str = "";
console.log([...str]);
Run Code Online (Sandbox Code Playgroud)

使用for...of

function split(str){
  const arr = [];
  for(const char of str)
    arr.push(char)
   
  return arr;
}

const str = "";
console.log(split(str));
Run Code Online (Sandbox Code Playgroud)

  • 我认为应该指出的是,不幸的是这仍然没有涵盖目前使用的很多表情符号。例如 `[...'‍♀️']` 变为 `["", "", "‍", "♀", "️"]`。这意味着不可能进行直接的字符串反转或符号比较。 (7认同)

Nic*_*ons 8

JavaScript 有一个新的 API(ES2023 的一部分)Intl.Segmenter,允许您根据字素(用户感知的字符串字符)分割字符串。使用此 API,您的拆分可能如下所示:

\n

\r\n
\r\n
const split = (str) => {\n  const itr = new Intl.Segmenter("en", {granularity: \'grapheme\'}).segment(str);\n  return Array.from(itr, ({segment}) => segment);\n}\n// See browser console for output\nconsole.log(split(\'\')); // [\'\']\nconsole.log(split(\'e\xcc\x81\')); // [\'e\xcc\x81\']\nconsole.log(split(\'\xe2\x80\x8d\xe2\x80\x8d\')); // [\'\xe2\x80\x8d\xe2\x80\x8d\']\nconsole.log(split(\'\xe2\x9d\xa4\xef\xb8\x8f\')); // [\'\xe2\x9d\xa4\xef\xb8\x8f\']\nconsole.log(split(\'\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f\')); // [\'\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f\']
Run Code Online (Sandbox Code Playgroud)\r\n
<p>See browser console for logs</p>
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n

这使您不仅可以处理由两个代码点(例如 )组成的表情符号,还可以处理其他字符,例如复合字符(例如:e\xcc\x81)、由 ZWJ 分隔的字符(例如:\xe2\x80\x8d\xe2\x80\x8d)、具有变体选择器的字符(例如: \xe2\x9d \xa4\xef\xb8\x8f)、带有表情符号修饰符的字符(例如:\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f)等。所有这些都不能通过调用字符串迭代器(通过使用 spread ...for..ofSymbol.iterator)来处理,如其他答案中所示,因为它们只会迭代字符串的代码点。

\n


Gin*_*den 6

完成此任务的最佳方法是使用可识别String.prototype[Symbol.iterator]Unicode 字符的本机。因此,Array.from在字符串上使用了简单易行的拆分 Unicode 字符的方法,例如:

const string = String.fromCodePoint(128514, 32, 105, 32, 102, 101, 101, 108, 32, 128514, 32, 97, 109, 97, 122, 105, 110, 128514);
Array.from(string);
Run Code Online (Sandbox Code Playgroud)

  • 同样,`[...'‍♀️']`变成`["", "", "‍", "♀", "️"]` (4认同)

rob*_*uck 5

ECMA 2015 中引入了一个标志来支持正则表达式中的 unicode 识别。

添加u到正则表达式会返回结果中的完整字符。

const withFlag = `ABDE`.match(/./ug);
const withoutFlag = `ABDE`.match(/./g);

console.log(withFlag, withoutFlag);
Run Code Online (Sandbox Code Playgroud)

这里还有更多相关内容