我需要对来自第三方包的类型切片进行排序。根据某些条件,顺序必须是升序或降序。
我想出的解决方案是:
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 行代码,其中大部分是重复的,似乎有点太多了。
从 Go 1.8 开始,有一种更简单的方法来对不需要定义新类型的切片进行排序。您只需将匿名函数传递给sort.Slice
函数即可。
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)
}
这将按升序排序,如果你想要相反的,只需在匿名函数中写a[i] > a[j]
即可。
你正在寻找sort.Reverse
.这会让你说:
sort.Sort(sort.Reverse(fooAscending(s)))
我下面的回答是基于您从第三方包收到的切片是基本 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 类型进行排序不需要实现属于排序的函数,例如 Len()。接口。对于复合类型,您只需要采用该路线。
只需使用适当的接口方法提供程序(例如 StringSlice、IntSlice 或 Float64Slice)包装基本类型的类型,然后排序即可。
切片按原地排序,因此不会返回已排序切片的副本。
接受的答案很好,但我不同意他们关于降序的建议:
a[i] > a[j]
对于sort.Slice
,提供的函数应该表示一个"小于"的实施:
func Slice(x interface{}, less func(i, j int) bool)
Slice
给定提供的less
函数对切片x
进行排序。如果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]
}
两者都应该返回相同的结果,但我认为一个更惯用。
https://golang.org/pkg/sort#Slice
也许您可以使用sort.Sort
方法来对切片进行排序。 :)
func TestSorted(t *testing.T) {
nums := []int{4, 3, 2, 3, 5, 2, 1}
// descending
sort.Sort(sort.Reverse(sort.IntSlice(nums)))
fmt.Println(nums) // [5 4 3 3 2 2 1]
// ascending
sort.Sort(sort.IntSlice(nums))
fmt.Println(nums) // [1 2 2 3 3 4 5]
}
您可以从 golang 的标准库中导入 "sort" 包。 然后,您可以使用"切片"或"切片稳定"功能对切片进行排序。 建议像这样使用第二个:
sort.SliceStable(yourSlice , anonnymousFunction)
例:包主
import (
"fmt"
"sort"
)
func main() {
a := []int{4,5,9,6,8,3,5,7,99,58,1}
sort.SliceStable(a, func(i,j int )bool{
//i,j are represented for two value of the slice .
return a[i] < a[j]
})
fmt.Println(a)
}
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 的链接
按升序排序:
package main
import (
"fmt"
"sort"
)
func main() {
// unsorted string and integer slices
strData := []string{"Go", "Bravo", "Gopher", "Alpha", "Grin", "Delta"}
intData := []int{5, 2, 6, 3, 1, 4}
// sort in-place in ascending order
sort.Ints(intData)
sort.Strings(strData)
// print
fmt.Println(intData)
fmt.Println(strData)
}
输出:
[Alpha Bravo Delta Go Gopher Grin]
[1 2 3 4 5 6]
按降序排序:
package main
import (
"fmt"
"sort"
)
func main() {
// unsorted int and string slices
strData := []string{"Go", "Bravo", "Gopher", "Alpha", "Grin", "Delta"}
intData := []int{5, 2, 6, 3, 1, 4}
// sort in-place in descending order
sort.Sort(sort.Reverse(sort.IntSlice(intData)))
sort.Sort(sort.Reverse(sort.StringSlice(strData)))
// print
fmt.Println(intData)
fmt.Println(strData)
}
输出:
[6 5 4 3 2 1]
[Grin Gopher Go Delta Bravo Alpha]
如果出于任何原因你不能或不想使用排序包,下面将实现气泡排序类型的排序(它接受 int64 切片并返回 int64 切片):
func sortSlice ( S []int64 ) []int64 {
// sort using bubblesort, comparing each pairs of numbers and ensuring that left is lower than right
for i := len(S); i > 0 ; i-- {
for j := 1; j < i; j++ {
if S[j-1] > S[j] {
// swap
intermediate := S[j]
S[j] = S[j-1]
S[j-1] = intermediate
}
}
}
return S
}