我需要对来自3rdparty包的类型进行排序。根据某些条件,订单必须是升序或降序。
我提出的解决方案是:
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 (v fooAscending) Less(i, j int) bool { return v[i].Amount < v[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 (v fooDescending) Less(i, j int) bool { return v[i].Amount > v[j].Amount }
if someCondition {
sort.Sort(fooAscending(array))
} else {
sort.Sort(fooDescending(array))
}
有没有更好的方法来做到这一点。这项任务的13行代码,其中大部分是重复的,似乎有点太多了。
答案 0 :(得分:25)
从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]
。
答案 1 :(得分:9)
您正在寻找sort.Reverse
。那会让你说:
sort.Sort(sort.Reverse(fooAscending(s)))
答案 2 :(得分:4)
我在下面的回答是基于这样的假设,即您从第三方软件包收到的切片是基本的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自行试用。
注意事项:
对基本Go类型进行排序不需要实现属于sort.Interface的Len()等函数。您只需要为复合类型采用该路由。
使用适当的接口方法提供程序包装基本类型的类型,例如StringSlice,IntSlice或Float64Slice,并排序。
切片就地排序,因此不会返回已排序切片的副本。
答案 3 :(得分:0)
`var names = []string{"b", "a", "e", "c", "d"}
sort.Strings(names)
fmt.Println("Sorted in alphabetical order", names)
sort.Sort(sort.Reverse(sort.StringSlice(names)))
fmt.Println("Sorted in reverse order", names)`
The Go Playgound https://play.golang.org/p/Q8KY_JE__kx的链接
答案 4 :(得分:0)
接受的答案很好,但我不同意他们关于降序的建议:
a[i] > a[j]
使用 sort.Slice
,提供的函数应该代表一个
“小于”的实现:
func Slice(x interface{}, less func(i, j int) bool)
Slice
根据提供的 x
函数对切片 less
进行排序。如果它恐慌
x
不是切片。
所以写一个“大于”函数,对给定的描述并不真实。 最好是反转索引:
package main
import (
"fmt"
"sort"
)
func main() {
a := []int{5, 3, 4, 7, 8, 9}
sort.Slice(a, func(i, j int) bool {
return a[j] < a[i]
})
fmt.Println(a) // [9 8 7 5 4 3]
}
两者都应该返回相同的结果,但我认为一个更惯用。