有一段时间我一直在正常化&通过以下方式去除文本:
// 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个循环,加上正则表达式很慢。
我的第一个想法是修改上面的函数直接在循环中执行lowercasings(removeAccentsBytes函数的第二部分)。但后来我决定将它全部组合成一个循环,包括转换函数。
关于这一点,我首先尝试从变换源中获取转换表,然后通过复制和修改它,但我似乎无法让它为我提供它用于的任何表格。转型。事实证明,即使norm.NFD = 1和norm.NFC = 0,我还没有弄清楚它如何解析参数为0或1的事实,并以某种方式从中获得转换表。
阅读它的代码我无论如何都能看到它的有效编写,显然超出了初学者的Go技能,所以我认为使用transform.Chain添加我自己的变换器会更好。 / p>
我无法在任何地方找到关于如何编写将被transform.Chain接受的变压器的任何指令。什么都没有。
有没有人知道如何为此制作变压器?
答案 0 :(得分:1)
func Chain(t ...Transformer) 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
}