如何检索[]符文的第一个“完整”字符?

时间:2014-12-23 21:54:53

标签: unicode go rune

我正在尝试编写一个函数

func Anonymize(name string) string

匿名化名称。以下是输入和输出对的一些示例,以便您了解它应该执行的操作:

Müller → M.
von der Linden → v. d. L.
Meyer-Schulze → M.-S.

此函数适用于由任意字符组成的名称。在实现此功能时,我遇到了以下问题:

给定一个[]runestring,我如何计算出我需要多少符文来获得一个完整的角色,完整的意思是所有修饰符和组合对应的角色都是也被采取了。例如,如果输入为[]rune{0x0041, 0x0308, 0x0066, 0x0067}(对应于字符串ÄBC,其中Ä表示为A和组合diaresis的组合),则该函数应返回2,因为前两个符文产生第一个字符,Ä 。如果我只是采取了第一个符文,我会得到A是不正确的。

我需要回答这个问题,因为我要匿名的名字可能以重音字符开头,我不想删除重音。

1 个答案:

答案 0 :(得分:2)

您可以尝试以下功能(灵感来自" Go language string length"):

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

请参阅this example

r := []rune{0x0041, 0x0308, 0x0066, 0x0041, 0x0308, 0x0067}
s := string(r)
fmt.Println(s, len(r), FirstGraphemeLen(s))

输出:

ÄfÄg 6 2

该字符串可能使用6个符文,但其第一个字母使用2。


OP FUZxxl使用了另一种方法,使用unicode.IsMark(r)

  

IsMark报告符文是否为标记字符(类别M)。

来源(来自FUZxxl' s play.golang.org)包括:

// take one character including all modifiers from the last name
r, _, err := ln.ReadRune()
if err != nil {
    /* ... */
}

aln = append(aln, r)

for {
    r, _, err = ln.ReadRune()
    if err != nil {
        goto done
    }

    if !unicode.IsMark(r) {
        break
    }

    aln = append(aln, r)
}

aln = append(aln, '.')
/* ... */