计算golang字符串中的字符

时间:2016-04-29 01:41:27

标签: string unicode go emoji string-length

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

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

根据我的阅读herehere,以下内容应该有效,但我似乎仍未获得正确的结果(过度计算):

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
}

这也不起作用:

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

我在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;
 }

5 个答案:

答案 0 :(得分:4)

您是否尝试过strings.Count

package main

import (
     "fmt"
     "strings"
 )

 func main() {
     fmt.Println(strings.Count("Hello, 世界", "")) // Returns 2
 }

答案 1 :(得分:3)

我编写了一个程序包,您可以执行以下操作:https://github.com/rivo/uniseg。它根据您要寻找的Unicode Standard Annex #29中指定的规则来中断字符串。这是在您的情况下使用它的方式:

package main

import (
    "fmt"

    "github.com/rivo/uniseg"
)

func main() {
    fmt.Println(uniseg.GraphemeClusterCount("Hello, 世界"))
}

这将按您期望的那样打印11

答案 2 :(得分:2)

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

package main

import (
    "fmt"
    "unicode/utf8"
)

func main() {
    str := "Hello, 世界"
    count := 0
    for len(str) > 0 {
        r, size := utf8.DecodeLastRuneInString(str)
        count++
        fmt.Printf("%c %v\n", r, size)

        str = str[:len(str)-size]
    }
    fmt.Println("count:",count)
}

答案 3 :(得分:1)

直接使用utf8.RuneCountInString()

package main

import (
    "fmt"
    "unicode/utf8"
)

func main() {
    str := "Hello, 世??界"
    fmt.Println("counts =", utf8.RuneCountInString(str))
}

答案 4 :(得分:0)

我认为最简单的方法是这样的:

package main

import "fmt"

func main() {
    str := "Hello, 世??界"
    var counter int
    for range str {
        counter++
    }
    fmt.Println(counter)
}

此版本打印 11