分析golang的slice排序

来源:互联网 发布:书生商友seo 编辑:程序博客网 时间:2024/05/29 18:40

今天写代码,牵扯到给一个slice排序的问题,发现go的sort包里支持自定义排序,果断拿来用了。

sort.Slice(priceList, func(i, j int) bool {        return priceList[i].RenewDate > priceList[j].RenewDate    })

上面这个是使用sort.Slice()的例子。

在此之前,先讲讲基础的Sort方法,

type Interface interface {    // Len is the number of elements in the collection.    Len() int    // Less reports whether the element with    // index i should sort before the element with index j.    Less(i, j int) bool    // Swap swaps the elements with indexes i and j.    Swap(i, j int)}func Sort(data Interface) {    n := data.Len()    quickSort(data, 0, n, maxDepth(n))}func quickSort(data Interface, a, b, maxDepth int) {    .    .    .}



我们发现,要实现sort排序,我们需要实现sort接口的三个方法,分别是Len()Less(i, j int) bool,和Swap(i, j int)。这三个方法的注释上面都有,我就不解释了。它接收Interface接口,拿到了Interface接口,就可以去调用实现了这个接口的类型所对应的三个方法。Sort方法内部会去调一个快排算法,既然是快排算法,里面肯定用到了less和swap,所以内部实现就不贴出来了。所以针对一般的sort.Sort(某个切片),使用例子如下:

type Person struct { Name string Age int}type PersonSlice [] Personfunc (a PersonSlice) Len() int {   // 重写 Len() 方法 return len(a)}func (a PersonSlice) Swap(i, j int){  // 重写 Swap() 方法 a[i], a[j] = a[j], a[i]}func (a PersonSlice) Less(i, j int) bool { // 重写 Less() 方法, 从大到小排序 return a[j].Age < a[i].Age}func main() { people := [] Person{  {"zhang wan", 15},  {"li zi", 31},  {"wang su", 32},  {"zhao miu", 28}, } sort.Sort(PersonSlice(people)) // 按照 Age 的逆序排序,参数传递给接口 fmt.Println(people)


接下来讲一个更高效的,那就是sort.Slice()方法了,

sort.Slice(priceList, func(i, j int) bool {        return priceList[i].RenewDate > priceList[j].RenewDate    })//使用func Slice(slice interface{}, less func(i, j int) bool) {    rv := reflect.ValueOf(slice)    swap := reflect.Swapper(slice)    length := rv.Len()    quickSort_func(lessSwap{less, swap}, 0, length, maxDepth(length))}//源码



如上所述,我直接写一个less函数作为函数对象传给Slice方法,这里其实相当于callback的思想了,然后swap和len方法系统帮我自动实现,len就是我的第一个参数的长度,swap用系统默认的交换算法,这样我就高效的编写了一个可以由我自己来定义排序顺序的struct切片排序,不仅简洁优雅,代码量小,而且容易被人理解,真是又一次体会到了go的魅力。

原创粉丝点击