2016-06-08 312 views
2

我需要对来自3rdparty包的类型切片进行排序。基于某些条件,订单必须是升序或降序。golang排序切片升序或降序

的解决方案,我想出是:

type fooAscending []foo 

func (v fooAscending) Len() int   { return len(v) } 
func (v fooAscending) Swap(i, j int)  { v[i], v[j] = v[j], v[i] } 
func (a fooAscending) Less(i, j int) bool { return a[i].Amount < a[j].Amount } 

type fooDescending []foo 

func (v fooDescending) Len() int   { return len(v) } 
func (v fooDescending) Swap(i, j int)  { v[i], v[j] = v[j], v[i] } 
func (a fooDescending) Less(i, j int) bool { return a[i].Amount > a[j].Amount } 


if something 
    sort.Sort(fooAscending(array)) 
} else { 
    sort.Sort(fooDescending(array)) 
} 

有没有更好的方式来做到这一点。这个任务的13行代码,大部分都是重复的,看起来有点过分。

回答

10

从Go 1.8开始,有一种更简单的方法可以对不需要定义新类型的片进行排序。您只需创建一个Less(匿名)lambda。

a := []int{5, 3, 4, 7, 8, 9} 
sort.Slice(a, func(i, j int) bool { 
    return a[i] < a[j] 
}) 
for _, v := range a { 
    fmt.Println(v) 
} 

这将升序排序,如果你想反其道而行之,干脆在lambda写a[i] > a[j]

2

我在下面的答案是基于这样的假设,即您从第三方包接收的片是基本的Go类型。

要对基本类型的片段进行排序,请使用排序包实用程序。这里是一个对字符串片段和int片段进行排序的例子。

package main 

import (
    "fmt" 
    "sort" 
) 

func main() { 
    sl := []string{"mumbai", "london", "tokyo", "seattle"} 
    sort.Sort(sort.StringSlice(sl)) 
    fmt.Println(sl) 

    intSlice := []int{3,5,6,4,2,293,-34} 
    sort.Sort(sort.IntSlice(intSlice)) 
    fmt.Println(intSlice) 
} 

上面的输出是:

[london mumbai seattle tokyo] 
[-34 2 3 4 5 6 293] 

转到Go Playground here尝试一下自己。

值得注意的几件事情:

  1. 排序基本围棋类型并不需要实现的功能,如莱恩()属于sort.Interface。您只需要为复合类型采用该路线。

  2. 只需使用合适的接口方法提供程序包装基本类型的类型即可。 StringSliceIntSliceFloat64Slice,然后分类。

  3. 切片就地排序,因此不返回已排序切片的副本。