前言

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

代码

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/C++编写超精美自定义控件(历时9年更新迭代/超202个控件/祖传原创)

    一.前言 无论是哪一门开发框架,如果涉及到UI这块,肯定需要用到自定义控件,越复杂功能越多的项目,自定义控件的数量就越多,最开始的时候可能每个自定义控件都针对特定的应用场景,甚至里面带了特定的场景的一 ...

  2. Qt编写的项目作品19-图片及视频TCP/UDP网络传输

    一.功能特点 多线程收发图片数据和解析图片数据,不卡主界面. 同时支持TCP和UDP两种模式,封装了TCP模式以及UDP模式的客户端类和服务端类. 图片传输客户端同时支持发送到多个服务端,可以作为一个 ...

  3. 即时通讯技术文集(第9期):Java NIO和Netty入门系列 [共19篇]

    为了更好地分类阅读52im.net 总计1000多篇精编文章,我将在每周三推送新的一期技术文集,本次是第9 期. [-1-] 少啰嗦!一分钟带你读懂Java的NIO和经典IO的区别 [链接] http ...

  4. asp.net mvc中换肤机制类库 ThemedViewEngines

    制作blog系统或者通用cms系统的时候,我们经常会用到Theme功能.asp.net mvc中的一种实现方式,是继承实现RazorViewEngine即可. 这是在GitHub中找到的一个示例:ht ...

  5. VEP注释文件下载网址

    Ensembl提供多个物种的注释文件: ftp://ftp.ensembl.org/pub/release-96/variation/VEP

  6. Redis学习笔记之spring-data-redis

    一.关于spring-data-redis spring-data-redis针对jedis提供了如下功能: 连接池自动管理,提供了一个高度封装的"RedisTemplate"类 ...

  7. 微服务实战系列(七)-网关springcloud gateway-copy

    1. 场景描述 springcloud刚推出的时候用的是netflix全家桶,路由用的zuul,但是据说zull1.0在大数据量访问的时候存在较大性能问题,2.0就没集成到springcloud中了, ...

  8. SSH 框架的搭建

    Structs1+spring+Hibernate Structs  相当于mvc设计模式中V.C,即jsp页面和Servlet: spring 管理业务逻辑,即Service: Hibernate ...

  9. bootwiki-Elasticsearch教程

    https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html Elasticsearch教程 Elasticse ...

  10. java加密算法入门(四)-加密算法汇总

    如基本的单向加密算法: BASE64 严格地说,属于编码格式,而非加密算法 MD5(Message Digest algorithm 5,信息摘要算法) SHA(Secure Hash Algorit ...