在 Golang 中实现排序

发布于 2021-11-04 14:18 ,所属分类:软件编程学习资料

CTO



GoRustPythonIstiocontainerdCoreDNSEnvoyetcdFluentdHarborHelmJaegerKubernetesOpenPolicyAgentPrometheusRookTiKVTUFVitessArgoBuildpacksCloudEventsCNIContourCortexCRI-OFalcoFluxgRPCKubeEdgeLinkerdNATSNotaryOpenTracingOperatorFrameworkSPIFFESPIREThanos






在 Golang 中实现排序

对数据列表进行排序是您发现自己经常编码的最常见任务之一。本文探讨了 Golang 中的一些技术,可以使任何数据集合的排序变得简单。


由于此任务在解决编码分配方面的极其常见,所有编程语言通常都提供现成的实用程序来对集合进行排序。Go 没有什么不同,它提供了用于执行所有可能的排序操作的排序包。

Gosort用于排序的标准包。排序函数就地对数据进行排序。对于基本数据类型,我们有内置函数,例如sort.Intssort.Strings。对于更复杂的类型,我们需要通过实现sort.Interface. Golangsortthe包实现了对内置类型和用户定义类型的排序。

对整数集合进行排序

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.Slicesort.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

mapsGolang中的无序集合,因此没有使用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]

参考资料

[1]

参考: https://rksurwase.medium.com/?p=9537c433d6e2


相关资源