如何解决带重音符的字符串键上的排序结构
我最近偶然发现一个问题,试图对包含法语字符串的键上的结构进行排序。古典的sort.SliceStable
并没有根据法语字母排序规则正确考虑重音字符。
非常幸运的是,collate软件包可以正确地做到这一点,但是我找不到不将其与sort.SliceStable
函数结合使用的直接在结构上使用的方法。
这我想出的似乎正确地工作:
import (
"fmt"
"sort"
"golang.org/x/text/collate"
"golang.org/x/text/language"
)
type SortFr struct {
Order int
Fr string
}
func main() {
// the int SortFr.Order reflects the correct french sort order
s := []SortFr{
SortFr{2,"côte"},SortFr{0,"cote"},SortFr{5,"coter"},SortFr{1,"coté"},SortFr{4,"cotée"},SortFr{3,"côté"},}
// incorrect sort order
sort.SliceStable(s,func(i,j int) bool {
return s[i].Fr < s[j].Fr
})
fmt.Println(s)
// correct sort order
cl := collate.New(language.french)
sort.SliceStable(s,j int) bool {
return cl.CompareString(s[i].Fr,s[j].Fr) == -1
})
fmt.Println(s)
}
此代码返回:
[{0 cote} {5 coter} {1 coté} {4 cotée} {2 côte} {3 côté}]
[{0 cote} {1 coté} {2 côte} {3 côté} {4 cotée} {5 coter}]
这是在大型结构上执行此操作的最有效方法吗?
解决方法
您的排序基于一个较小的函数,该函数仅调用cl.CompareString()
。您希望更简单吗?您必须根据Fr
字段告诉您要排序的方式/某处,这就是您可以做到的方式。
sort.SliceStable()
是通用的,可以对任何切片进行排序。为此,它必须在引擎盖下使用反射,这比不必求助于反射的解决方案要慢。因此,如果您想对较大的部分进行排序,则实施sort.Interface
是有利可图的。
var cl = collate.New(language.French)
type FrSlice []SortFr
func (s FrSlice) Len() int { return len(s) }
func (s FrSlice) Less(i,j int) bool { return cl.CompareString(s[i].Fr,s[j].Fr) < 0 }
func (s FrSlice) Swap(i,j int) { s[i],s[j] = s[j],s[i] }
然后使用它:
s := []SortFr{
// ...
}
sort.Stable(FrSlice(s))
还要注意,sort.Sort()
可能比sort.Stable()
快一些,因为前者不必保证相等元素的原始顺序。因此,如果不需要保持元素相等的原始顺序,请使用sort.Sort()
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。