如何获取string中的字符数?

如何获得Go中string的字符数?

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

你可以从utf8包中尝试RuneCountInString

返回p中的符文数

正如这个脚本所说明的那样:“世界”的长度可能是6(用中文写成:“世界”),但它的符文数是2:

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

“冷冻” 在评论中补充道:

其实你可以只通过types转换来执行len()
len([]rune("世界"))将打印2 。 在Go 1.3的Leats中。


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

什么是人物?

正如在string博客文章中提到的 , 字符可以跨越多个符文
例如,一个' e '和'◌◌'(尖锐的“\ u0301”)可以结合起来形成'é'(NFD中的“ e\u0301 ”)。 这两个符文一起是一个字符

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

  • 以起始者开始的一系列符文,
  • 一个不会修改或与任何其他符文向后结合的符文,
  • 其次是可能是空的序列的非首发,即,符文(通常是重音)。

规范化algorithm一次处理一个字符。

使用这个包和它的Itertypes ,“字符”的实际数目是:

 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“Compatibility Decomposition”

有一种方法可以通过将string转换为[] rune as len([]rune(YOUR_STRING))来获得没有任何包的符len([]rune(YOUR_STRING))

 package main import "fmt" func main() { russian := "Спутник и погром" english := "Sputnik & pogrom" fmt.Println("count of bytes:", len(russian), len(english)) fmt.Println("count of runes:", len([]rune(russian)), len([]rune(english))) } 

字节数30 16

计数符文16 16

取决于你对“angular色”的定义。 如果“符文等于一个字符”对你的任务来说可以(通常不是),那么VonC的答案对你来说是完美的。 否则,应该可能会注意到,很less有一些Unicodestring中的符文数量是一个有趣的值的情况。 即使在这种情况下,如果可能的话,在处理符文时“遍历”string以推断计数,以避免使UTF-8解码工作翻倍。

如果您需要考虑字形集群,请使用正则expression式或unicode模块。 由于字形集群的长度是无限的,因此计算码位(符号)或字节的数量也是有效的。 如果您想消除极长的序列,请检查序列是否符合stream式安全文本格式 。

 package main import ( "regexp" "unicode" "strings" ) func main() { str := "\u0308" + "a\u0308" + "o\u0308" + "u\u0308" str2 := "a" + strings.Repeat("\u0308", 1000) println(4 == GraphemeCountInString(str)) println(4 == GraphemeCountInString2(str)) println(1 == GraphemeCountInString(str2)) println(1 == GraphemeCountInString2(str2)) println(true == IsStreamSafeString(str)) println(false == IsStreamSafeString(str2)) } func GraphemeCountInString(str string) int { re := regexp.MustCompile("\\PM\\pM*|.") return len(re.FindAllString(str, -1)) } func GraphemeCountInString2(str string) int { length := 0 checked := false index := 0 for _, c := range str { if !unicode.Is(unicode.M, c) { length++ if checked == false { checked = true } } else if checked == false { length++ } index++ } return length } func IsStreamSafeString(str string) bool { re := regexp.MustCompile("\\PM\\pM{30,}") return !re.MatchString(str) }