前言

有时候我们需要处理一份数据,需要多个字段作为条件,联合进行排序。

代码

package main

import (
"fmt"
"sort"
) // 数据类型
type Change struct {
user string
language string
lines int
} // sort接口方法之一(Less)
type lessFunc func(p1, p2 *Change) bool // 数据集类型, 与排序(多字段单独排序)比较, less字段的数据类型不再是 func(p1, p2 *Change) bool
// 而是 []func(p1, p2 *Change) bool 因为在第一个比较的值相等的情况下, 还要比较第二个值, 所以这里需要多个比较函数
type multiSorter struct {
changes []Change
less []lessFunc
} type OrderedBy []lessFunc func (ob OrderedBy) Sort(changes []Change) {
ms := &multiSorter{
changes: changes,
less: ob,
}
sort.Sort(ms)
} // Len 为sort接口方法之一
func (ms *multiSorter) Len() int {
return len(ms.changes)
} // Swap 为sort接口方法之一
func (ms *multiSorter) Swap(i, j int) {
ms.changes[i], ms.changes[j] = ms.changes[j], ms.changes[i]
} // Less 为sort接口方法之一
func (ms *multiSorter) Less(i, j int) bool {
// 为了后面编写简便, 这里将需要比较的两个元素赋值给两个单独的变量
p, q := &ms.changes[i], &ms.changes[j]
// Try all but the last comparison.
var k int
// 由于可能有多个需要排序的字段, 也就对应了多个less函数, 当第一个字段的值相等时,
// 需要依次尝试比对后续其他字段的值得大小, 所以这里需要获取比较函数的长度, 以便遍历比较
for k = 0; k < len(ms.less)-1; k++ {
// 提取比较函数, 将函数赋值到新的变量中以便调用
less := ms.less[k]
switch {
case less(p, q):
// 如果 p < q, 返回值为true, 不存在两个值相等需要比较后续字段的情况, 所以这里直接返回
// 如果 p > q, 返回值为false, 则调到下一个case中处理
return true
case less(q, p):
// 如果 p > q, 返回值为false, 不存在两个值相等需要比较后续字段的情况, 所以这里直接返回
return false
}
// 如果代码走到这里, 说明ms.less[k]函数比较后 p == q; 重新开始下一次循环, 更换到下一个比较函数处理
continue
}
// 如果代码走到这里, 说明所有的比较函数执行过后, 所有比较的值都相等
// 直接返回最后一次的比较结果数据即可
return ms.less[k](p, q)
} var changes = []Change{
{"gri", "Go", 100},
{"ken", "C", 150},
{"glenda", "Go", 200},
{"rsc", "Go", 200},
{"r", "Go", 100},
{"ken", "Go", 200},
{"dmr", "C", 100},
{"r", "C", 150},
{"gri", "Smalltalk", 80},
} func main() {
// 预定义排序函数: 按照姓名升序排列
user := func(c1, c2 *Change) bool {
return c1.user < c2.user
}
// 预定义排序函数: 按照语言升序排列
language := func(c1, c2 *Change) bool {
return c1.language < c2.language
}
// 预定义排序函数: 按照行数升序排列
increasingLines := func(c1, c2 *Change) bool {
return c1.lines < c2.lines
}
//预定义排序函数: 按照行数降序排列
decreasingLines := func(c1, c2 *Change) bool {
return c1.lines > c2.lines
} // 按照姓名升序排列
OrderedBy([]lessFunc{user}).Sort(changes)
fmt.Println("By user:\t\t", changes) // 按照姓名升序排列, 姓名相同的按行数升序排列
OrderedBy([]lessFunc{user, increasingLines}).Sort(changes)
fmt.Println("By user,<lines:\t\t", changes) // 按姓名升序排列, 姓名相同的按行数降序排列
OrderedBy([]lessFunc{user, decreasingLines}).Sort(changes)
fmt.Println("By user,>lines:\t\t", changes) // 按语言升序排列, 语言相同按行数升序排列
OrderedBy([]lessFunc{language, increasingLines}).Sort(changes)
fmt.Println("By language,<lines:\t", changes) // 按语言升序排列, 语言相同按行数升序排列, 行数也相同的, 按姓名升序排列
OrderedBy([]lessFunc{language, increasingLines, user}).Sort(changes)
fmt.Println("By language,<lines,user:", changes)
}

运行结果

By user:                 [{dmr C 100} {glenda Go 200} {gri Go 100} {gri Smalltalk 80} {ken C 150} {ken Go 200} {r Go 100} {r C 150} {rsc Go 200}]
By user,<lines: [{dmr C 100} {glenda Go 200} {gri Smalltalk 80} {gri Go 100} {ken C 150} {ken Go 200} {r Go 100} {r C 150} {rsc Go 200}]
By user,>lines: [{dmr C 100} {glenda Go 200} {gri Go 100} {gri Smalltalk 80} {ken Go 200} {ken C 150} {r C 150} {r Go 100} {rsc Go 200}]
By language,<lines: [{dmr C 100} {ken C 150} {r C 150} {r Go 100} {gri Go 100} {ken Go 200} {glenda Go 200} {rsc Go 200} {gri Smalltalk 80}]
By language,<lines,user: [{dmr C 100} {ken C 150} {r C 150} {gri Go 100} {r Go 100} {glenda Go 200} {ken Go 200} {rsc Go 200} {gri Smalltalk 80}]

go 结构体多字段多因素排序的更多相关文章

  1. ABAP中不修改内表参照的结构,给内表/结构体增加字段

    Situation: DATA:       itab  TYPE STANDARD TABLE OF zsrsodtla_stru1,      wa_itab TYPE zsrsodtla_str ...

  2. go语言之进阶篇非结构体匿名字段

    1.非结构体匿名字段 示例 : package main import "fmt" type mystr string //自定义类型,给一个类型改名 type Person st ...

  3. Golang通过反射拼接一个结构体所有字段

    golang通过反射拼接一个结构体所有字段 需求 将一个结构体所有字段以"|"连接拼接成字符串 golang 不同类型拼接成string使用Sprintf比较麻烦,如果一个结构体有 ...

  4. Java的 「 “ 结构体 ”」 与 「 “ 自定义排序 ” 」

    Java里面的结构体可以靠class来实现,如果相对结构体进行排序,需要写一个接口,class 自定义的名字 implements Comparator<结构体(自己定义的class类的名字)& ...

  5. C++线性表通过结构体实现操作和结构体字符串快速排序和shell排序结合

    #include<iostream> #include<string> #define ml 10 using namespace std; typedef struct{// ...

  6. 为什么建议使用Guid结构体做为数据库及排序时的主键

    在.net2.0中,Guid结构体表示一个全局唯一标识符,是一个在生成时就可以肯定为全世界唯一的16字节值.Guid在数据库中通常可以作为各种排序的主键.比如 public class Company ...

  7. [GO]非结构体匿名字段

    package main import ( "fmt" ) type mystr string //给一个类型重命名 type Person struct { name strin ...

  8. matlab学习笔记12_2创建结构体数组,访问标量结构体,访问非标量结构体数组的属性,访问嵌套结构体中的数据,访问非标量结构体数组中多个元素的字段

    一起来学matlab-matlab学习笔记12 12_2 结构体 创建结构体数组,访问标量结构体,访问非标量结构体数组的属性,访问嵌套结构体中的数据,访问非标量结构体数组中多个元素的字段 觉得有用的话 ...

  9. 利用sort对结构体进行排序

    我定义了一个学生类型的结构体来演示sort排序对结构体排序的用法 具体用法看代码 #include<iostream> #include<string> #include< ...

  10. C++ list结构体变量排序

    以下内容是自己整理的根据结构体里面的不同变量,对list排序的实例,若有问题可以留言.仅供参考. #include <iostream> #include <list> #in ...

随机推荐

  1. Qt编写可视化大屏电子看板系统32-模块10大屏地图

    一.前言 大屏地图模块采用浏览器模块+echart组件,Qt自带了webkit或者webengine模块,其中在win上mingw编译器的Qt5.6以后的版本,没有了浏览器模块,这个就需要用第三方的浏 ...

  2. Qt开源作品7-高亮按钮控件

    一.前言 这个高亮按钮控件并非本人原创作品,是参考的Qt界的一个大师级人物公孙二狗的作品,各位有兴趣可以去搜索查看,在原作者的代码上,我只是改成了自己的控件的框架结构,然后完善了一些细节,比如增加了各 ...

  3. Typora设置自定义脚本上传图片

    搭建图床服务 这里利用CloudFlare搭建免费的图床服务 cf-image-hosting 部署Pages $ git clone https://github.com/ifyour/cf-ima ...

  4. 即时通讯技术文集(第16期):IM架构设计技术精选(第一部分) [共17篇]

    为了更好地分类阅读总计1000多篇精编文章,我将在每周三推送新的一期技术文集,本次是第16 期. [- 1 -] 浅谈IM系统的架构设计 [链接] http://www.52im.net/thread ...

  5. Appium_iOS自动化测试之Appium Log

                  Xcode WebDriverAgentRunner配置参考: https://www.cnblogs.com/dreamhighqiu/p/11023363.html 1 ...

  6. Solution Set - “让朝阳洒向晚霞,在星空下涂鸦”

    目录 0.「UR #12」「UOJ #182」a^-1 + b problem 1.「NOI Simu.」点 2.「集训队互测 2023」「QOJ #5100」卡牌游戏 3.「NOI Simu.」简单 ...

  7. Solution -「AGC 031E」Snuke the Phantom Thief

    \(\mathscr{Description}\)   Link.   在一个网格图内有 \(n\) 个格子有正价值,给出四种限制:横 / 纵坐标不大于 / 不小于 \(a\) 的格子不能选超过 \( ...

  8. 【转载】Geojson常用工具,收藏备用

    收集了网上几个比较好用的网站,收藏备用 1.Geojson数据下载器:http://datav.aliyun.com/tools/atlas/#&lat=33.54139466898275&a ...

  9. [新]Java8的新特性

    原文首发在我的博客:https://blog.liuzijian.com/post/86955c3b-9635-47a0-890c-f1219a27c269.html 1.Lambda表达式 lamb ...

  10. vue平铺日历组件

    vue日历自定义平铺组件 <sy-icon @click="preMon" class="copy-icon" iconClass="iconj ...