2016-04-29 183 views
4

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

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)) 
} 

我要寻找的目标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; 
} 
+0

您正在寻找[从UAX#29 “字形簇边界” 算法]中的实现(http://unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries)。 –

+0

我认为是对的。我尝试了从这个答案http://stackoverflow.com/a/26728555/547291计算字形的两个实现,但我遇到了同样的麻烦,但也许字形群边界计数更多我想要的? –

+0

这个问题的答案将“字形集群”与“字符规范化”混为一谈(都有严重错误)。 –

回答

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) 
} 
+1

这个数*符文*,而不是*字形*:'str:=“”'计数2而不是1。 –

+0

什么是“AX”,为什么它应该是1? –

+1

这是'U + 1F1E6 U + 1F1FD',它应该是奥兰群岛的旗帜。任何其他区域性指标符号都会有相同的结果(也许''在您的系统上呈现得更好?)。 –

1

你试过strings.Count

package main 

import (
    "fmt" 
    "strings" 
) 

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

在“Hello,世界”的例子中,我希望它数11,因为有11个字符,而不是2.我将编辑我的问题来澄清。 –