如何计算 javascript 中带有表情符号的字符串的正确长度?

新手上路,请多包涵

我有点问题。

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

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

 👶🏻👦🏻👧🏻👨🏻👩🏻👱🏻‍♀️👱🏻👴🏻👵🏻👲🏻👳🏻‍♀️👳🏻👮🏻‍♀️👮🏻👷🏻‍♀️👷🏻💂🏻‍♀️💂🏻🕵🏻‍♀️👩🏻‍⚕️👨🏻‍⚕️👩🏻‍🌾👨🏻‍🌾👨🏻‍🌾👨🏻‍🌾👨🏻‍🌾👨🏻‍🌾👨🏻‍🌾👨🏻‍🌾👨🏻‍🌾👨🏻‍🌾👨🏻‍🌾👨🏻‍🌾👨🏻‍🌾👨🏻‍🌾👨🏻‍🌾👨🏻‍🌾

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

console.log(bio.length)

其中 bio 是输入文本,我得到 221。我如何“解析”字符串输入以获得正确的长度?这是关于unicode的问题吗?

解决了

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

我试过了:

 var Grapheme = require('grapheme-splitter');
var splitter = new Grapheme();
console.log(splitter.splitGraphemes(bio).length);

长度是37,效果很好!

原文由 Stackedo 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.1k
2 个回答
  1. str.length 给出 UTF-16 单元的计数。

  2. 以代码点(以字符为单位)获取字符串长度的 Unicode 证明方法是 [...str].length 因为可迭代协议将字符串拆分为代码点。

  3. 如果我们需要字素(字素簇)的长度,我们有这些本机方法:

一个。 RegExp 中的 Unicode 属性转义。参见示例: Unicode-aware version of \wMatching emoji

b. [Intl.Segmenter——](https://github.com/tc39/proposal-intl-segmenter) 即将推出,可能在 ES2021 中。可以在最新的 V8 版本中使用标志进行测试(实现与 V8 86 中的最新规范同步)。在 V8 87 中未标记(已发货)。

也可以看看:

原文由 vsemozhebuty 发布,翻译遵循 CC BY-SA 4.0 许可协议

TL;DR 有解决方案,但它们并非在所有情况下都有效。 Unicode 感觉像是一门黑暗艺术。

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

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

现在,存在前端 vs 后端问题:你解决了字符数问题,因此它对人类用户来说很好用,现在你的单个表情符号正好超过了数据库中分配的字段大小。 mongo 等数据库的问题不大,但可能是 SQL 数据库的问题,其中字段分配是保守的。这意味着您如何解决问题将取决于最困难的限制来自何处。

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

 Array.from(str)

当角色组合在一起并处理 星界 时,这将分崩离析。

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

  • 尽可能使用解决前端问题的方法,然后确保解决存储问题
  • 如果无法调整数据库或其他存储,则对公布的前端限制更加保守
  • 限制可以输入的字符类型
  • 明确指出长度计算的局限性

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

其他页面阅读:

原文由 Andre M 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题