我正在尝试编写一个函数
func Anonymize(name string) string
匿名化名称。以下是输入和输出对的一些示例,以便您了解它应该执行的操作:
Müller → M.
von der Linden → v. d. L.
Meyer-Schulze → M.-S.
此函数适用于由任意字符组成的名称。在实现此功能时,我遇到了以下问题:
给定一个[]rune
或string
,我如何计算出我需要多少符文来获得一个完整的角色,完整的意思是所有修饰符和组合对应的角色都是也被采取了。例如,如果输入为[]rune{0x0041, 0x0308, 0x0066, 0x0067}
(对应于字符串ÄBC,其中Ä表示为A和组合diaresis的组合),则该函数应返回2,因为前两个符文产生第一个字符,Ä 。如果我只是采取了第一个符文,我会得到A是不正确的。
我需要回答这个问题,因为我要匿名的名字可能以重音字符开头,我不想删除重音。
答案 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, '.')
/* ... */