一尘不染

如何获取字符串中的字符数?

go

如何在Go中获取字符串的字符数?

例如,如果我有一个字符串,则"hello"该方法应返回5。我看到len(str)返回的字节数 ,而不是
字符的数量,以便len("£")返回2而不是1,因为£被编码有在UTF-8的两个字节。


阅读 279

收藏
2020-07-02

共1个答案

一尘不染

您可以RuneCountInString从utf8包中尝试。

返回p中的符文数

该脚本所示:“世界”的长度可能为6(用中文写成“世界”),但符文数为2:

package main

import "fmt"
import "unicode/utf8"

func main() {
    fmt.Println("Hello, 世界", len("世界"), utf8.RuneCountInString("世界"))
}

实际上len(),只需键入强制转换即可完成符文。 len([]rune("世界"))将打印2。在Go 1.3中。


借助CL 108985(2018年5月,适用于Go
1.11),len([]rune(string))现已进行了优化。(修复了问题24923

编译器len([]rune(string))自动检测模式,并将其替换为r:= range调用。

添加一个新的运行时函数以计算字符串中的符文。修改编译器以检测模式,len([]rune(string)) 并将其替换为新的符文计数运行时函数。

RuneCount/lenruneslice/ASCII                  27.8ns ± 2%  14.5ns ± 3%  -47.70%  (p=0.000 n=10+10)
RuneCount/lenruneslice/Japanese                126ns ± 2%    60ns ± 2%  -52.03%  (p=0.000 n=10+10)
RuneCount/lenruneslice/MixedLength             104ns ± 2%    50ns ± 1%  -51.71%  (p=0.000 n=10+9)

Stefan Steiger指向博客文章“
Go中的文本规范化

什么是角色?

正如字符串博客文章中提到的那样, 角色可以跨越多个符文
例如,一个’ e‘和’◌́◌́’(急性“ \ u0301”)可以组合成一个’é’(e\u0301在NFD中为“ ”)。
这两个符文合在一起是一个角色

字符的定义可能会因应用程序而异。
为了 规范化, 我们将其定义为:

  • 以起动器开始的一系列符文,
  • 不会修改或向后组合任何其他符文的符文,
  • 随后可能是空的非启动器序列,即具有此功能的符文(通常为重音符号)。

归一化算法一次处理一个字符。

使用该软件包及其Iter类型,“字符”的实际数量为:

package main

import "fmt"
import "golang.org/x/text/unicode/norm"

func main() {
    var ia norm.Iter
    ia.InitString(norm.NFKD, "école")
    nc := 0
    for !ia.Done() {
        nc = nc + 1
        ia.Next()
    }
    fmt.Printf("Number of chars: %d\n", nc)
}

在这里,它使用Unicode规范化形式 NFKD“兼容性分解”


Oliver的答案指出
UNICODE TEXT SEGMENTATION
是可靠确定某些重要文本元素(用户感知的字符,单词和句子)之间默认边界的唯一方法。

为此,您需要一个像 rivo / uniseg 这样的外部库,它可以执行
Unicode Text Segmentation

将实际计数“ 字形
”,其中多个码点可被组合成一个用户感知的字符。

package uniseg

import (
    "fmt"

    "github.com/rivo/uniseg"
)

func main() {
    gr := uniseg.NewGraphemes("👍🏼!")
    for gr.Next() {
        fmt.Printf("%x ", gr.Runes())
    }
    // Output: [1f44d 1f3fc] [21]
}

即使有三个符文(Unicode代码点),也有两个字素。

2020-07-02