计算golang字符串中的字符

Bjo*_*che 9 string unicode string-length go emoji

我试图计算"角色".也就是说,如果一个字符串包含一个可打印的"字形"或"组合字符"(或者某人通常会认为是一个字符),我希望它计数为1.例如,字符串"Hello,世界",应该计数11,因为有11个字符,一个人会看到这个并说有11个字形.

utf8.RuneCountInString()在大多数情况下运行良好,包括ascii,重音符,亚洲字符甚至表情符号.但是,据我所知,符文对应于代码点,而不是字符.当我尝试使用基本的表情符号时它可以工作,但是当我使用具有不同肤色的表情符号时,我得到了错误的计数:https://play.golang.org/p/aFIGsB6MsO

从我在这里这里读到 的内容应该可行,但我似乎仍然没有得到正确的结果(它过度计数):

func CountCharactersInString(str string) int {
    var ia norm.Iter
    ia.InitString(norm.NFC, str)
    nc := 0
    for !ia.Done() {
        nc = nc + 1
        ia.Next()
    }
    return nc
}
Run Code Online (Sandbox Code Playgroud)

这也不起作用:

func GraphemeCountInString(str string) int {
    re := regexp.MustCompile("\\PM\\pM*|.")
    return len(re.FindAllString(str, -1))
}
Run Code Online (Sandbox Code Playgroud)

我在Objective C中寻找类似的东西:

+ (NSInteger)countCharactersInString:(NSString *) string {
    // --- Calculate the number of characters enterd by user and update character count label
    NSInteger count = 0;
    NSUInteger index = 0;
    while (index < string.length) {
        NSRange range = [string rangeOfComposedCharacterSequenceAtIndex:index];
        count++;
        index += range.length;
    }
    return count;
 }
Run Code Online (Sandbox Code Playgroud)

p_m*_*mcp 12

你试过strings.Count吗?

package main

import (
     "fmt"
     "strings"
 )

 func main() {
     fmt.Println(strings.Count("Hello, ??", "")) // Returns 2
 }
Run Code Online (Sandbox Code Playgroud)


Oli*_*ver 9

我写了一个允许你这样做的包:https : //github.com/rivo/uniseg。它根据您正在寻找的Unicode 标准附件 #29 中指定的规则来拆分字符串。以下是在您的情况下如何使用它:

package main

import (
    "fmt"

    "github.com/rivo/uniseg"
)

func main() {
    fmt.Println(uniseg.GraphemeClusterCount("Hello, ??"))
}
Run Code Online (Sandbox Code Playgroud)

这将按11您的预期打印。


Fer*_*ras 6

直接本机使用 utf8.RuneCountInString()

package main

import (
    "fmt"
    "unicode/utf8"
)

func main() {
    str := "Hello, ??"
    fmt.Println("counts =", utf8.RuneCountInString(str))
}
Run Code Online (Sandbox Code Playgroud)

  • 或者使用 utf8.RuneCountInString 更直接 (2认同)

Jia*_* YD 5

参考 API 文档示例。\n https://golang.org/pkg/unicode/utf8/#example_DecodeLastRuneInString

\n\n
package main\n\nimport (\n    "fmt"\n    "unicode/utf8"\n)\n\nfunc main() {\n    str := "Hello, \xe4\xb8\x96\xe7\x95\x8c"\n    count := 0\n    for len(str) > 0 {\n        r, size := utf8.DecodeLastRuneInString(str)\n        count++\n        fmt.Printf("%c %v\\n", r, size)\n\n        str = str[:len(str)-size]\n    }\n    fmt.Println("count:",count)\n}\n
Run Code Online (Sandbox Code Playgroud)\n

  • 这算的是 *runes*,而不是 *graphemes*:`str := ""` 算的是 2 而不是 1。 (2认同)