代码之家  ›  专栏  ›  技术社区  ›  Stackedo

如何在javascript中使用emojis计算字符串的正确长度?

  •  3
  • Stackedo  · 技术社区  · 6 年前

    我有点问题。

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

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

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

    正如您所看到的,没有220个emoji(有37个emoji),但是如果我在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。它工作得很好!

    4 回复  |  直到 6 年前
        2
  •  1
  •   Laion Camargo    6 年前
    function fancyCount2(str){
      const joiner = "\u{200D}";
      const split = str.split(joiner);
      let count = 0;
    
      for(const s of split){
        //removing the variation selectors
        const num = Array.from(s.split(/[\ufe00-\ufe0f]/).join("")).length;
        count += num;
      }
    
      //assuming the joiners are used appropriately
      return count / split.length;
    }
    
        3
  •  1
  •   Andre M    6 年前

    tl;dr有解决方案,但它们在每种情况下都不起作用。Unicode就像一种黑色的艺术。

    我所看到的各种解决方案似乎都存在局限性,这个问题超越了emoji,并且涵盖了Unicode范围内的其他字符。考虑_)可以存储为_)或e+226;_,如果使用 combing characters . 这甚至可以导致两个看起来相同的字符串 not being equal . 另外请注意,在某些情况下,存储时单个emoji可以是11个字符,结果是22个字节,假设是utf16。

    处理方式以及字符组合或显示方式在浏览器和操作系统之间甚至可能有所不同。所以,虽然你可能认为你破解了它,但另一个环境可能会破坏它。一定要测试它的重要性。

    现在,有一个前端和后端的问题:你解决了字符计数问题,所以它对人类用户很有效,现在你的单个emoji正好超过了数据库中分配的字段大小。对于Mongo这样的数据库来说,这不是什么问题,但是对于SQL数据库,字段分配是保守的。这意味着你如何解决你的问题将取决于最困难的限制出现在哪里。

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

    Array.from(str)
    

    当字符组合和处理 astral planes .

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

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

    另外,考虑到这个问题的复杂性,是否有一个流行的JS库已经处理了这个问题,这可能值得一看?我在写作时没有找到。希望这在某种程度上会成为JavaScript的核心。

    其他要阅读的页面:

        4
  •  0
  •   Luke    6 年前

    从下面的示例中可以看到,这与Unicode编码有关,

    有一些很好的资源,比如我举这个例子的那个。

    https://blog.jonnew.com/posts/poo-dot-length-equals-two

    console.log("👩‍❤️‍💋‍👩".length === 11);