Go+自定义排序教程(4.2)
基础概念
自定义排序要求待排序的对象实现sort.Interface接口,只要实现一下三个方法即可
Len() int // 需要排序的集合的长度
Less(i, j int) bool // 比较i位置和j位置元素顺序
Swap(i, j int) // 替换i位置和j位置元素
最简单排序示例就是定义一个struct,分别实现以上三个方法,即可使用sort.Sort排序,其中Less函数是定义排序规则的方法,这里可以决定两个比较元素的顺序,返回true代表不用交换,返回false则需要交换位置。
程序会有以下输出:
students: [{Lilei 18 78 79} {Hanmeimei 17 79 99} {Hetingting 19 71 68}]
by age : [{Hanmeimei 17 79 99} {Lilei 18 78 79} {Hetingting 19 71 68}]
自定义排序
如果想灵活的排序字段可以使用排序函数的别名,然后声明多种不同规则的排序函数,首先有两个主要struct,一个是OrderBy,它是排序函数的别名,用于转换不同类型的排序,另一个是排序器StudentSorter,它是内部有待排序数据和对应的排序规则函数OrderBy,同时StudentSorter实现了sort.Interface接口,可以使用sort.Sort排序。
程序会有以下输出:
students: [{Lilei 18 78 79} {Hanmeimei 17 79 66} {Hetingting 19 71 68}]
By EnglishScore : [{Hetingting 19 71 68} {Lilei 18 78 79} {Hanmeimei 17 79 66}]
By MathScore : [{Hanmeimei 17 79 66} {Hetingting 19 71 68} {Lilei 18 78 79}]
如果想多个字段按照优先级排序呢,比如先按照EnglishScore排序,如果相等则接着按照MathScore排序呢?我们可以重新设计排序器,其中排序器同样带有带排序数据,不相同的是排序规则为多个,执行排序时候会遍历这些排序规则,如果第一个排序器可以决定顺序就返回,否则就计算下一个排序规则,知道排出顺序。
程序会有以下输出:
students: [{Lilei 18 78 79} {Hanmeimei 17 78 66} {Hetingting 19 71 68}]
By EnglishScore: [{Hetingting 19 71 68} {Hanmeimei 17 78 66} {Lilei 18 78 79}]
By EnglishScore and MathScore: [{Hetingting 19 71 68} {Hanmeimei 17 78 66} {Lilei 18 78 79}]
可以看到当EnglishScore都是78的时候使用了MathScore作为排序的结果。
因为本质上,排序是给出一个固定的规则下,有一个固定的顺序,所以我们可以做一些有意思的排序,比如奇数在前,偶数在后,这个例子和第一个例子只有Less函数的实现不同,其它都是相同的,Less函数逻辑也很简单,如果都是奇数或者都是偶数返回true,如果i是奇数,返回true,否则返回false。
程序会有以下输出:
students: [{Lilei 18 78 79} {Hanmeimei 17 79 99} {Hetingting 19 71 68}]
by age : [{Hetingting 19 71 68} {Hanmeimei 17 79 99} {Lilei 18 78 79}]
可以看到顺序已经变了,并且是奇数在前偶数在后。
在做一个有意思的排序,我们假设考试分数百分制,忽略具体分数,而是按照等级排序,等级A:90-100 B:80-90 C:70-80 D: 60-70 E:小于60,同级排名不分先后,这里和第一个例子也是只修改了Less的实现,因为它是管排序规则的,或者对应级别后,因为字符串可以直接比较大小,所以直接返回对比大小。
程序会有以下输出:
students: [{Hanmeimei 17 79 99} {Lilei 18 78 79} {Hetingting 19 66 68}]
by EnglishScore: [{Hetingting 19 66 68} {Hanmeimei 17 79 99} {Lilei 18 78 79}]
可以看到66排序在前,79和78顺序没有动,因为它俩级别都是C。
- 点赞
- 收藏
- 关注作者
评论(0)