JS高精度计算字符串的长度

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

在开发项目中,我们经常需要精确地计算字符串的长度。这不仅包括常规的字母和数字,还需要考虑多种语言的字符以及表情符号和颜文字等特殊字符。特别是在处理用户生成内容、国际化应用和聊天应用时,准确的字符串长度计算显得尤为重要。本篇文章将介绍一种高精度计算字符串长度的方法,能够处理包括中文字符、表情符号和颜文字在内的多种字符类型。


一、Unicode是什么?

在这里插入图片描述
Unicode,全称为Unicode标准(The Unicode Standard),其官方机构Unicode联盟所用的中文名称为统一码,又译作万国码、统一字符码、统一字符编码,是信息技术领域的业界标准,其整理、编码了世界上大部分的文字系统,使得电脑能以通用划一的字符集来处理和显示文字,不但减轻在不同编码系统间切换和转换的困扰,更提供了一种跨平台的乱码问题解决方案。Unicode由非营利机构Unicode联盟(Unicode Consortium)负责维护,该机构致力让Unicode标准取代既有的字符编码方案,因为既有方案编码空间有限,亦不适用于多语环境。

Unicode伴随着通用字符集ISO/IEC 10646的标准而发展,同时也以书本的形式对外发表。Unicode至今仍在不断增修,每个新版本都加入更多新的字符。目前最新的版本为2022年9月公布的15.0.0,已经收录超过14万个字符(第十万个字符在2005年获采纳)。Unicode标准不仅仅只是为文字指定代码。除了涵盖视觉上的字形、编码方法、标准的字符编码资料外,联盟官方出版品还包含了关于各书写系统的细节及呈现方式,如规范化的准则、拆分、测序、绘制、双向文本显示、书写方向、字符特性(如大小写字母)等等。此外还提供参考资料和视觉图像,以帮助开发者和设计师正确应用标准。

Unicode备受认可,为ISO纳入国际标准,成为通用字符集,即 ISO/IEC 10646。Unicode兼容ISO/IEC 10646,能完整对应各个版本标准。Unicode广泛应用于电脑软件的国际化与本地化过程。很多新科技,如可扩展置标语言(Extensible Markup Language,简称:XML)、Java编程语言以及现代操作系统,都采用Unicode来编码。Unicode最普遍的编码格式是和ASCII兼容的UTF-8,以及和UCS-2兼容的UTF-16。

二、详细解释

1.基本多文种平面 (Basic Multilingual Plane, BMP)

基本多文种平面(Basic Multilingual Plane, BMP),或称基本平面或〇号平面(Plane 0),是统一码的一区块编码,从0000至FFFF。
中文字符:Unicode 范围 0x4e00 到 0x9fff 和 0x3400 到 0x4dbf 的字符被认为是中文字符,长度计为 2。

在这里插入图片描述

2.高代理项 (High Surrogates)

高代理项是 Unicode 中用于表示超出基本多文种平面 (BMP) 的字符的一部分。高代理项的代码范围是 0xD800 到 0xDBFF

图示可能会看不清楚 建议自行百度或维基百科
在这里插入图片描述

3.其他字符

除了高代理项和中文字符外,还包括拉丁字母、数字、标点符号、货币符号、各种符号和表情符号等。

在这里插入图片描述

其他的知识就不过多赘述 有需要了解请自行百度亦或维基百科进行查询 接下来直接展示代码片段

我在查阅资料时 看到一位大佬整理的 感觉很详细 可以参考 点击跳转

三、代码展示

代码如下(示例):


/**
 * *计算字符串的长度,同时考虑中文字符的存在,每个字符计算2个字符。
 * @param str  要计算长度的字符串
 * @returns 字符串的长度
 */
export function calculateStringLength(str: string) {
    let length = 0
    for (let i = 0; i < str.length; i++) {
        const char = str.charCodeAt(i)
        // 检查是否为基本多文种平面的中文字符
        if ((char >= 0x4e00 && char <= 0x9fff) || (char >= 0x3400 && char <= 0x4dbf)) {
            length += 2
        } else if (char >= 0xd800 && char <= 0xdbff) {
            // 检查是否为高代理对
            if (i + 1 < str.length) {
                const nextChar = str.charCodeAt(i + 1)
                if (nextChar >= 0xdc00 && nextChar <= 0xdfff) {
                    // 检查是否为低代理对
                    // 检查代理对是否表示扩展区域的中文字符
                    const fullChar = (char - 0xd800) * 0x400 + (nextChar - 0xdc00) + 0x10000
                    if (fullChar >= 0x20000 && fullChar <= 0x2a6df) {
                        length += 2
                    } else {
                        length += 1
                    }
                    i++ // 跳过下一个字符,因为它是代理对的一部分
                } else {
                    length += 1 // 单独的高代理项,理论上不应该出现,但还是增加长度1以保证计数的完整性
                }
            }
        } else {
            length += 1
        }
    }

    return length
}

总结

代码实际上还有可优化空间 各位自行斟酌

以上就是本篇文章的全部内容啦 如有错误欢迎大佬评论区留言指教~~~

  • 37
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值