戈朗排序切片升序或降序



我需要对来自第三方包的类型切片进行排序。根据某些条件,顺序必须是升序或降序。

我想出的解决方案是:

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]

去游乐场 这里 自己尝试一下。

需要注意的几点:

  1. 对基本 Go 类型进行排序不需要实现属于排序的函数,例如 Len()。接口。对于复合类型,您只需要采用该路线。

  2. 只需使用适当的接口方法提供程序(例如 StringSlice、IntSlice 或 Float64Slice)包装基本类型的类型,然后排序即可。

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

接受的答案很好,但我不同意他们关于降序的建议:

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
}

最新更新