1

我正在尝试编写一个函数

func Anonymize(name string) string

匿名化名称。以下是一些输入和输出对的示例,以便您了解它应该做什么:

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

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

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

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

4

1 回答 1

2

您可以尝试以下功能(受“ Go语言字符串长度”启发):

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

这个例子

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 的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, '.')
/* ... */
于 2014-12-23T22:50:17.227 回答