Go语言sort包排序
1,说明
本文主要总结go语言sort包排序的基本用法,并不实现底层排序算法。
本着不要重复造轮子的思想,工程开发中为了提高效率肯定是用sort包进行相关排序。
这里总结下基础用法,当作以后开发的笔记。
2,sort包排序三要素排序
1,简介:
sort包的底层实现是多种排序的算法,例如快排,插入等等。调用时并不公开,也无需定义用那种算法。
sort包内部会根据实际情况,自动选择最高效的排序算法。
2,实现:
1,实现原理
1,如果掌握多种底层排序算法的话,应该可以提炼出排序算法的三要素,即序列长度,两个元素比较结果,两个元素交换方式。
2,go语言sort包就是这么做的,提供三个方法,用来实现三要素。分别是Len,Less,Swap
3,调用的时候不需要查看底层如何实现,只需要用户定义出三要素,go语言就会按照底层最高效的算法按照用户定义的三要素对序列进行排序
4,在实际工程开发中,对string,int等排序应该非常多。sort包提供了更加便捷的方法,不用用户自己定义三要素,可直接调用进行排序。
2,排序序列要求
为了让sort包能识别序列,对序列进行排序,就必须让序列实现sort.interface{}接口。
只有实现了sort.interface{}接口的序列,sort包才能进行排序。
3,总结
根据上面的原理,可以总结出,序列必须实现sort.interface{}接口,即序列的类型必须实现sort.interface{}下的方法,就是排序三要素,Len,Less,Swap。这三个方法。
然后调用sort.Sort()方法,可根据定义对序列最终排序。
4,sort包定义了sort.Reverse()方法,对当前定义的排序规则取反,也就是反向排序。
5,实现
//定义序列类型
type TestStringList []string
//定义排序三要素
func (t TestStringList) Len() int { ... }
func (t TestStringList) Less(i,j int) bool { ... }
func (t TestStringList) Swap(i,j int) { ... }
//进行排序
sort.Sort(TestStringList)
//根据定义的排序规则取反
sort.Sort(sort.Reverse(TestStringList))
3,实例
//定义序列类型,只要此类型实现了sort.interface{}接口(实现三要素方法),就可以对此类型排序
type TestStringList []string
//元素个数
func (t TestStringList) Len() int {
return len(t)
}
//比较结果
func (t TestStringList) Less(i, j int) bool {
return t[i] < t[j]
}
//交换方式
func (t TestStringList) Swap(i, j int) {
t[i], t[j] = t[j], t[i]
}
func SortPackageDemo() {
stringList := TestStringList{
"1-php",
"2-java",
"3-golang",
"4-c",
"5-cpp",
"6-python",
}
//按照定义的规则排序
sort.Sort(stringList)
fmt.Println(stringList)
//返回值
//[1-php 2-java 3-golang 4-c 5-cpp 6-python]
//按照定义的规则反向排序
sort.Sort(sort.Reverse(stringList))
fmt.Println(stringList)
//返回值
//[6-python 5-cpp 4-c 3-golang 2-java 1-php]
}
注意:这种排序方式,对任何实现了sort.interface{}接口的序列,都可以排序
3,sort包常见便捷排序
1,简介
1,工程项目中,比如对字符串,数字序列的排序场景应该非常多,每个排序都用上面三要素实现,还是有点麻烦。
所以go语言提供了常用序列的便捷排序方法。无需定义三要素。直接调用即可得出结果。
2,go语言具体提供了字符串,整形,双精度浮点数的快捷排序。
2,具体实现
1,说明
1,sort包提供了三个切片类型sort.StringSlice,sort.IntSlice,sort.Float64Slice。可以对这三种类型进行便捷排序。
2,需要对序列满足以上三个切片类型之一,可直接调用sort.Sort()方法进行排序,无需定义三要素。
3,其实实现原理就是把满足这三种切片类型的三要素函数直接定义在了底层,用户无需定义,直接调用sort.Sort()方法即可拿到排序结果,默认升序。如果需要逆序,调用sort.Reverse()函数即可。
2,实现
demoString := sort.StringSlice{
...
}
//正序
sort.Sort(demoString)
//逆序
sort.Sort( sort.Reverse(demoString) )
3,实例
func speedySort(){
//直接定义字符串序列为StringSlice
stringTmp := sort.StringSlice{
"3-golang",
"4-c",
"5-cpp",
"1-php",
"2-java",
"6-python",
}
sort.Sort(stringTmp)
fmt.Println(stringTmp)
//[1-php 2-java 3-golang 4-c 5-cpp 6-python]
sort.Sort( sort.Reverse(stringTmp) )
fmt.Println(stringTmp)
//[6-python 5-cpp 4-c 3-golang 2-java 1-php]
intTmp := []int{
6,3,9,8,1,2,5,7,
}
//转换intTmp为IntSlice类型
sort.Sort( sort.IntSlice(intTmp) )
fmt.Println(intTmp)
//[1 2 3 5 6 7 8 9]
sort.Sort( sort.Reverse( sort.IntSlice(intTmp) ) )
fmt.Println(intTmp)
//[9 8 7 6 5 3 2 1]
}
3,sort.Slice排序
1,简介
概览:
Go 1.8之后的版本,Go语言在 sort 包中提供了 sort.Slice() 函数进行更为简便的排序方法。
sort.Slice() 函数只要求传入需要排序的数据,以及一个排序时对元素的回调函数
实现:
sort.Slice(tmp,func(i,j int){
return tmp[i]<tmp[j]
})
2,实例
func demoSortSlice(){
a := []int{6,3,9,8,1,2,5,7}
sort.Slice(a, func(i, j int) bool {
return a[i]>a[j]
})
fmt.Println(a)
//[9 8 7 6 5 3 2 1]
}
4,多维切片排序
1,概览
说明
前面说的所有的排序,都是一维切片的排序,也就是说只有一个排序参考纬度。
如果对多维的切片排序,可能有多个字段,不同的字段有不同的排序优先级,这里示例下多位排序的写法。
原理
多维排序是一维排序派生而来,所以也是依托最基本的排序三要素,长度,比较结果,位置交换。
可以得出,对多维切片的排序,是利用不同的排序字段比较结果来进行位置交换,然后得出结果。不同排序字段
的优先级可在比较结果(Less)方法内设置,最后进行排序。
总之一句话,其他的不变,只需要在Less方法中,根据不同的排序字段,设置不通的数据比较优先级,最后调用方法即可得出结果。
实现
func (l langSlice) Less(i,j int) bool {
if l[i]["type"] != l[j]["type"] {
return l[i]["type"] < l[j]["type"]
}
return l[i]["name"] < l[j]["name"]
}
type不一致的时候,先根据type排序。然后再根据name排序。
2,实例
这里定义了一个描述编程语言的二维map切片,先按照type排序,然后按照name排序。
1,sort.interface{}实现
type langSlice []map[string]string
func (l langSlice) Len() int {
return len(l)
}
func (l langSlice) Less(i,j int) bool {
if l[i]["type"] != l[j]["type"] {
return l[i]["type"] < l[j]["type"]
}
return l[i]["name"] < l[j]["name"]
}
func (l langSlice) Swap(i,j int){
l[i],l[j] = l[j],l[i]
}
func demoMapSort(){
lang := langSlice{
{"type": "front-end", "name": "css"},
{"type": "after-end", "name": "php"},
{"type": "os", "name": "mac"},
{"type": "front-end", "name": "js"},
{"type": "os", "name": "ubuntu"},
{"type": "after-end", "name": "java"},
{"type": "front-end", "name": "html"},
{"type": "after-end", "name": "go"},
{"type": "os", "name": "windows"},
{"type": "after-end", "name": "python"},
{"type": "os", "name": "centos"},
}
sort.Sort(lang)
fmt.Println(lang)
//[map[name:go type:after-end] map[name:java type:after-end] map[name:php type:after-end] map[name:python type:after-end] map[name:css type:front-end] map[name:html type:front-end] map[name:js type:front-end] map[name:centos type:os] map[name:mac type:os] map[name:ubuntu type:os] map[name:windows type:os]]
}
2,sort.Slice实现
func demoMapSliceSort() {
//定义了语言切片
lang := []map[string]string{
{"type": "front-end", "name": "css"},
{"type": "after-end", "name": "php"},
{"type": "os", "name": "mac"},
{"type": "front-end", "name": "js"},
{"type": "os", "name": "ubuntu"},
{"type": "after-end", "name": "java"},
{"type": "front-end", "name": "html"},
{"type": "after-end", "name": "go"},
{"type": "os", "name": "windows"},
{"type": "after-end", "name": "python"},
{"type": "os", "name": "centos"},
}
sort.Slice(lang, func(i, j int) bool {
if lang[i]["type"] != lang[j]["type"] {
return lang[i]["type"] < lang[j]["type"]
}
return lang[i]["name"] < lang[j]["name"]
})
fmt.Println(lang)
}