为了账号安全,请及时绑定邮箱和手机立即绑定

Go:为 code.google.com/p/go.text/transform 制作转换器

Go:为 code.google.com/p/go.text/transform 制作转换器

Go
慕容森 2021-08-10 16:23:26
一段时间以来,我一直在通过以下方式对文本进行规范化和去重音:// Local helper function for normalization of UTF8 strings.func isMn (r rune) bool {        return unicode.Is(unicode.Mn, r) // Mn: nonspacing marks    }// This map is used by RemoveAccents function to convert non-accented characters.var transliterations = map[rune]string{'Æ':"E",'Ð':"D",'Ł':"L",'Ø':"OE",'Þ':"Th",'ß':"ss",'æ':"e",'ð':"d",'ł':"l",'ø':"oe",'þ':"th",'Œ':"OE",'œ':"oe"}//  removeAccentsBytes converts accented UTF8 characters into their non-accented equivalents, from a []byte.func removeAccentsBytesDashes(b []byte) ([]byte, error) {    mnBuf := make([]byte, len(b))    t := transform.Chain(norm.NFD, transform.RemoveFunc(isMn), norm.NFC)    n, _, err := t.Transform(mnBuf, b, true)    if err != nil {        return nil, err    }    mnBuf = mnBuf[:n]    tlBuf := bytes.NewBuffer(make([]byte, 0, len(mnBuf)*2))    for i, w := 0, 0; i < len(mnBuf); i += w {        r, width := utf8.DecodeRune(mnBuf[i:])        if r=='-' {            tlBuf.WriteByte(' ')        } else {            if d, ok := transliterations[r]; ok {                tlBuf.WriteString(d)            } else {                tlBuf.WriteRune(r)            }        }        w = width    }    return tlBuf.Bytes(), nil}之后,我将整个内容小写并应用一系列正则表达式。这种做法非常繁重。我认为我应该能够在一个循环中完成整个字节,而不是 10 个循环,而且正则表达式很慢。我的第一个想法是修改上面的函数以直接在循环中执行小写(removeAccentsBytes 函数的第二部分)。但后来我决定我想把它全部组合成一个循环,包括转换函数。在这一点上,我首先尝试从转换源中获取转换表,然后通过复制和修改它,但我似乎无法让它给我它用于转换的任何表。事实证明,即使 norm.NFD = 1 和 norm.NFC = 0,我还没有弄清楚它如何解析参数为 0 或 1 的事实,并以某种方式从中获得转换表。阅读它的代码我可以看到它无论如何都写得很高效,而且显然超出了初学者的 Go 技能,所以我认为使用 transform.Chain 添加我自己的转换器可能会更好。我在任何地方都找不到关于如何编写transform.Chain 接受的转换器的任何说明。没有什么。有没有人有任何关于我如何为此制作变压器的信息?
查看完整描述

1 回答

?
不负相思意

TA贡献1777条经验 获得超10个赞

func Chain(t ...Transformer) Transformer

需要一个transform.Transformer数组


type Transformer interface {

    Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error)

}

所以你只需要创建一个实现 Transformer 接口的类型:


type DenormalizeAndDeaccent struct {

}


func (t *DenomarlizeAndDeaccent) Transform(dst, src []byte, atEOF bool) (int, int, error)   {

    result, err := removeAccentsBytesDashes(src)

    if err != nil {

        return 0, 0, nil

    }

    n := copy(dst, result)

    if n < len(src) {

        err = ErrShortDst

    }

    return n, len(src), err

}


查看完整回答
反对 回复 2021-08-10
  • 1 回答
  • 0 关注
  • 179 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信