在 Golang 中实现排序
发布于 2021-11-04 14:18 ,所属分类:软件编程学习资料
关注微信公众号《云原生CTO》更多云原生干货等你来探索
专注于云原生技术
分享
提供优质云原生开发
视频技术培训
面试技巧
,及技术疑难问题解答
云原生技术分享不仅仅局限于Go
、Rust
、Python
、Istio
、containerd
、CoreDNS
、Envoy
、etcd
、Fluentd
、Harbor
、Helm
、Jaeger
、Kubernetes
、OpenPolicyAgent
、Prometheus
、Rook
、TiKV
、TUF
、Vitess
、Argo
、Buildpacks
、CloudEvents
、CNI
、Contour
、Cortex
、CRI-O
、Falco
、Flux
、gRPC
、KubeEdge
、Linkerd
、NATS
、Notary
、OpenTracing
、OperatorFramework
、SPIFFE
、SPIRE
和Thanos
等
在 Golang 中实现排序
对数据列表进行排序是您发现自己经常编码的最常见任务之一。本文探讨了
Golang
中的一些技术,可以使任何数据集合的排序变得简单。
由于此任务在解决编码分配方面的极其常见,所有编程语言通常都提供现成的实用程序来对集合进行排序。Go
没有什么不同,它提供了用于执行所有可能的排序操作的排序包。
Go
有sort
用于排序的标准包。排序函数就地对数据进行排序。对于基本数据类型,我们有内置函数,例如sort.Ints
和sort.Strings
。对于更复杂的类型,我们需要通过实现sort.Interface
. Golang
的sortthe
包实现了对内置类型和用户定义类型的排序。
对整数集合进行排序
该sort.Ints
函数按升序对整数切片进行排序。
packagemain
import(
"fmt"
"sort"
)
funcmain(){
intSlice:=[]int{4,5,2,1,3,9,7,8,6,10}
fmt.Println(sort.IntsAreSorted(intSlice))//false
sort.Ints(intSlice)
fmt.Println(intSlice)//[12345678910]
fmt.Println(sort.IntsAreSorted(intSlice))//true
}
该sort.IntsAreSorted
方法还用于检查整数切片是否处于其排序形式。
对字符串集合进行排序
该sort.Strings
函数按升序对一段字符串进行排序。
packagemain
import(
"fmt"
"sort"
)
funcmain(){
fruitList:=[]string{"Apple","Watermelon","Orange","Pear","Cherry","Strawberry"}
fmt.Println(sort.StringsAreSorted(fruitList))//false
sort.Strings(fruitList)
fmt.Println(fruitList)//[AppleCherryOrangePearStrawberryWatermelon]
fmt.Println(sort.StringsAreSorted(fruitList))//false
}
该sort.StringsAreSorted
方法还用于检查字符串切片是否处于其排序形式。
对浮动集合进行排序
该sort.Float64s
函数按升序对浮点值切片进行排序。
packagemain
import(
"fmt"
"math"
"sort"
)
funcmain(){
floatArray:=[]float64{math.NaN(),-0.25,-1.32,0.92,4.812,2.111}
//NaNreturnsanIEEE754“not-a-number”value.
fmt.Println(sort.Float64sAreSorted(floatArray))//false
/*Float64sAreSortedreportswhethertheslicexissortedinincreasingorder,
withnot-a-number(NaN)valuesbeforeanyothervalues.*/
sort.Float64s(floatArray)
fmt.Println(floatArray)//[NaN-1.32-0.250.922.1114.812]
fmt.Println(sort.Float64sAreSorted(floatArray))//true
}
math.NaN()
返回 IEEE 754
“非数字”值。Float64sAreSorted()
报告切片 x
是否按升序排序,非数字 (NaN
) 值在任何其他值之前。
使用匿名函数对结构集合进行排序
要在 Golang
中对结构的切片进行排序,您需要将less
函数与sort.Slice
或sort.SliceStable
方法一起使用。您需要提供less
用于比较结构字段的函数的实现。以下是我们如何根据姓名和年龄对一部分人进行排序,例如:
packagemain
import(
"fmt"
"sort"
)
typePersonstruct{
namestring
ageint
}
var(
personList=[]Person{
{"Olivia",20},
{"Jeremy",40},
{"Thomas",30},
{"Judith",31},
{"Angie",33}}
)
funcmain(){
//SortingbyPersonbyAge
sort.Slice(personList,func(i,jint)bool{
returnpersonList[i].age<personList[j].age
})
fmt.Println("Sortedbyage:",personList)
//Sortedbyage:[{Olivia20}{Thomas30}{Judith31}{Angie33}{Jeremy40}]
//SortingbyPersonbyName
sort.Slice(personList,func(i,jint)bool{
returnpersonList[i].name<personList[j].name
})
fmt.Println("Sortedbyname:",personList)
//Sortedbyname:[{Angie33}{Jeremy40}{Judith31}{Olivia20}{Thomas30}]
}
less
函数返回true
将导致索引i
处的元素排序到比索引j
更低的位置(在已排序的切片中,索引i
处的元素将排在最前面)。否则,如果返回false
,则索引为j
的元素将排在前面。
sort.Slice
之间的区别在于,sort.SliceStable
后者会保持相等元素的原始顺序,而前者可能不会。
使用 Len、Less 和 Swap 对自定义数据结构进行排序
对于更复杂的类型,我们需要通过实现来创建我们自己的排序sort.Interface
:
typeInterfaceinterface{
Len()int
Less(i,jint)bool
Swap(i,jint)
}
下面的例子说明了这种类型的实现。
packagemain
import(
"fmt"
"sort"
)
typeLengthBasedStrings[]string
func(sLengthBasedStrings)Len()int{
returnlen(s)
}
func(sLengthBasedStrings)Swap(i,jint){
s[i],s[j]=s[j],s[i]
}
func(sLengthBasedStrings)Less(i,jint)bool{
returnlen(s[i])<len(s[j])
}
funcmain(){
words:=[]string{"rust-lang","golang","java","c","c++","dot-net","perl"}
sort.Sort(LengthBasedStrings(words))
fmt.Println("SortingbyLength:",words)
//SortingbyLength:[cc++perljavagolangdot-netrust-lang]
}
原始列表— [“rust-lang”、“golang”、“java”、“c”、“c++”、“dot-net”、“perl”]
排序列表— [“c”、“c++”、“perl”、“java”、“golang”、“dot-net”、“rust-lang”]
定义了一个新类型 LengthBasedStrings
来保存其中的字符串列表。这种类型实现了所需的接口,因此很容易与sort.Sort()
方法一起使用。Sort()
方法的定义是
func sort.Sort(data sort.Interface)
排序maps keys或values
maps
是Golang
中的无序集合,因此没有使用sort
包对maps
进行排序的规定。但是,如果您确实需要对maps
进行排序,则可以通过分别切出键和值来为其编写自定义实现。
packagemain
import(
"fmt"
"sort"
)
funcmain(){
items:=map[string]int{
"coin":12,
"chair":3,
"pen":4,
"bottle":9,
}
keys:=make([]string,0,len(items))
forkey:=rangeitems{
keys=append(keys,key)
}
sort.Strings(keys)
for_,key:=rangekeys{
fmt.Printf("%s%d\n",key,items[key])
}
}
结论
在Golang
中,通过使用排序包对数据集合进行排序非常简单,上面给出的解决方案应该能够满足您将面临的大多数情况。
5.3 参考资料
参考[1]
参考资料
参考: https://rksurwase.medium.com/?p=9537c433d6e2
相关资源