如何用JavaScript中的表情符号计算字符串的正确长度?

Sta*_*edo 5 javascript node.js emoji

我有点问题

我正在使用NodeJS作为后端。现在,用户拥有一个“传记”字段,用户可以在其中写一些关于他自己的东西。

假设此字段的最大长度为220,并将其作为输入:

???????????????????????????????????????? 
Run Code Online (Sandbox Code Playgroud)

如您所见,没有220个表情符号(有37个表情符号),但是如果我在nodejs服务器中这样做

console.log(bio.length)
Run Code Online (Sandbox Code Playgroud)

输入文本在何处,我得到221。如何“解析”字符串输入以获得正确的长度?关于Unicode是否有问题?

解决了

我使用了这个库:https : //github.com/orling/grapheme-splitter

我尝试过:

var Grapheme = require('grapheme-splitter');
var splitter = new Grapheme();
console.log(splitter.splitGraphemes(bio).length);
Run Code Online (Sandbox Code Playgroud)

长度为37。效果很好!

vse*_*byt 9

str.length给出UTF-16单位的数量。Unicode验证的以代码点(以字符为单位)获取字符串长度的方法是[...str].length可迭代协议将字符串拆分为代码点。

也可以看看:

每个软件开发人员绝对,肯定必须绝对了解Unicode和字符集(无借口!)

每个JavaScript开发人员应该了解的Unicode知识

JavaScript存在Unicode问题

ES2015中支持Unicode的正则表达式

深度的ES6字符串(和Unicode 、?)

  • @R3m `[...new Intl.Segmenter().segment('‍‍‍')].length` 如果您需要 `1` 则给出 `1` (字素)。 (7认同)
  • 破坏示例字符串会返回 37 吗?130 对我来说。 (4认同)
  • 那么,我们需要定义最大长度应该是什么单位。我们有 221 个 UTF-16 单元、131 个 Unicode 点(字符)或 37 个组合字素。 (2认同)
  • 这个问题非常要求输出 37 而不是 130 的代码。“[...str].length”对于将表情符号作为一个单位进行计数是不正确的。您可能想在回答中澄清这一点,以免给人们带来不必要的麻烦。 (2认同)

And*_*e M 5

TL;DR 有一些解决方案,但它们并不适用于所有情况。Unicode 感觉像是一门黑暗艺术。

\n\n

我见过的各种解决方案似乎都存在局限性,问题超出了表情符号范围,还涵盖了 Unicode 范围内的其他字符。如果使用组合字符,则考虑 \xc3\xa9 可以存储为 \xc3\xa9 或 e + \xe2\x80\x98 。这甚至可能导致两个看起来相同的字符串不相等。另请注意,在某些情况下,单个表情符号在存储时可以是 11 个字符,因此假设为 UTF16,则为 22 个字节。

\n\n

处理方式以及字符组合或显示方式甚至可能因浏览器和操作系统而异。因此,虽然您可能认为自己已经破解了它,但另一个环境可能会破坏它。一定要测试重要的地方。

\n\n

现在,存在前端与后端问题:您解决了字符计数问题,因此它对于人类用户来说效果很好,现在您的单个表情符号直接超过了数据库中分配的字段大小。对于 mongo 等数据库来说问题不大,但对于 SQL 数据库可能会出现问题,因为 SQL 数据库的字段分配比较保守。这意味着您如何解决问题将取决于最困难的限制出现在哪里。

\n\n

请注意,基本解决方案确实涉及将字符串转换为数组并获取长度,接受限制:

\n\n
Array.from(str)\n
Run Code Online (Sandbox Code Playgroud)\n\n

当角色组合起来并处理星体位面时,这将分崩离析。

\n\n

一些考虑到限制的高级方法:

\n\n
    \n
  • 尽可能使用解决前端问题的方法,然后确保存储问题得到解决
  • \n
  • 如果数据库或其他存储可以调整\xe2\x80\x99,则对公布的前端限制更加保守
  • \n
  • 限制可以输入的字符类型
  • \n
  • 清楚地表明长度计算的限制
  • \n
\n\n

此外,考虑到问题的复杂性,是否有一个流行的 JS 库已经可以处理这个问题可能值得看看?在撰写本文时我没有找到。希望这会在某个时候成为 Javascript 的核心。

\n\n

其他需要阅读的页面:

\n\n\n


Cre*_*154 5

我在这里回答了类似的问题

但基本上,它是:

''.match(/./gu).length == 1
Run Code Online (Sandbox Code Playgroud)

作为 :

''.length == 2
Run Code Online (Sandbox Code Playgroud)

我原来的帖子更精确

  • 并不适用于所有情况。例如, `"‍❤️‍‍".match(/./gu).length` 输出 `8` (7认同)