微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

带重音符的字符串键上的排序结构

如何解决带重音符的字符串键上的排序结构

我最近偶然发现一个问题,试图对包含法语字符串的键上的结构进行排序。古典的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 举报,一经查实,本站将立刻删除。