Golang中如何理解反向排序

Golang中如何理解反向排序 这里可能有些非常简单的东西我没理解,但我实在想不通反向排序的工作原理。

https://golang.org/pkg/sort/#example_Reverse

要对切片进行排序,我这样做:

sort.Sort(myslice)

但要反向排序,我必须这样做:

sort.Sort(sort.Reverse(myslice))

根据文档说明,“Reverse返回数据的逆序”,那么sort.Reverse不应该是按逆序排序,然后sort.Sort再把切片恢复成正常顺序吗?然而如果我只执行sort.Reverse,似乎什么变化都没有发生。


更多关于Golang中如何理解反向排序的实战教程也可以访问 https://www.itying.com/category-94-b0.html

7 回复

好的,我明白了。这虽然有点让我脑筋转不过弯,但我理解了。

谢谢。

更多关于Golang中如何理解反向排序的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


我确实注意到了提到接口而不是切片,但当时没有真正理解。这个描述很好且很有道理,我会构建几个示例来实际观察它的运行效果。谢谢。

你在耍小聪明 😉

文档明确指出 sort.Sort 接收的是 sort.Interface 接口类型,而不是切片!

该接口需要实现三个方法:Len、Swap 和 Less。其中 Less 方法接收切片的两个元素作为参数,如果第一个元素应该排在第二个元素之前,则返回 true。

sort.Reverse 会接收 sort.Interface 并对其 Less 方法的结果取反,从而反转排序顺序。

这样解释清楚了吗?

除了使用 p.reverse(及相关代码),您确实可以使用 sort.Reverse。

此外,我建议针对 “sortByKey” 布尔值创建两种不同的排序接口实现。基本上,只需定义两种类型:

type pairSortValue []Pair
type pairSortKey []Pair

…并为两者都实现 Len()、Swap() 和 Less() 方法。

当您需要排序时:

sort.Sort(pairSortValue(ps))
sort.Sort(sort.Reverse(pairSortKey(ps)))

(其中 ps 是 Pair 的切片。)

我尝试了一下,看起来都能理解,这样实现按键或值对键/值结构进行排序,并且能够反转排序顺序,你觉得怎么样?

package main

import "fmt"
import "sort"

type Pair struct {
	Key   string
	Value int
}

type PairList struct {
	p         []Pair
	sortByKey bool
	reverse   bool
}

func (p PairList) Len() int      { return len(p.p) }
func (p PairList) Swap(i, j int) { p.p[i], p.p[j] = p.p[j], p.p[i] }
func (p PairList) Less(i, j int) bool {
	if p.sortByKey {

我已经重写了它,现在看起来好多了。

github.com

digininja/go_practice/blob/master/sort/main.go

package main

import "fmt"
import "sort"

type Pair struct {
	Key   string
	Value int
}

type PairListValueSort []Pair
type PairListKeySort []Pair
type PairList []Pair

func (p PairListValueSort) Len() int      { return len(p) }
func (p PairListValueSort) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func (p PairListValueSort) Less(i, j int) bool {
	return p[i].Value < p[j].Value
}

此文件已被截断。显示完整内容

在Go语言中,sort.Reverse函数本身并不会执行排序操作,它只是返回一个包装了原始数据的新接口,该接口的Less方法被反转了。

让我用一个完整的例子来解释:

package main

import (
    "fmt"
    "sort"
)

func main() {
    numbers := []int{3, 1, 4, 1, 5, 9, 2, 6}
    
    fmt.Println("原始切片:", numbers)
    
    // 正常排序(升序)
    sort.Sort(sort.IntSlice(numbers))
    fmt.Println("升序排序:", numbers)
    
    // 重置数据
    numbers = []int{3, 1, 4, 1, 5, 9, 2, 6}
    
    // 反向排序(降序)
    sort.Sort(sort.Reverse(sort.IntSlice(numbers)))
    fmt.Println("降序排序:", numbers)
    
    // 只调用 Reverse 不会改变数据
    numbers = []int{3, 1, 4, 1, 5, 9, 2, 6}
    reversed := sort.Reverse(sort.IntSlice(numbers))
    fmt.Println("只调用 Reverse:", numbers)
    
    // 需要调用 Sort 才会实际排序
    sort.Sort(reversed)
    fmt.Println("调用 Sort 后:", numbers)
}

输出结果:

原始切片: [3 1 4 1 5 9 2 6]
升序排序: [1 1 2 3 4 5 6 9]
降序排序: [9 6 5 4 3 2 1 1]
只调用 Reverse: [3 1 4 1 5 9 2 6]
调用 Sort 后: [9 6 5 4 3 2 1 1]

关键点在于:

  • sort.Reverse返回一个包装器,它反转了Less方法的逻辑
  • 原本的Less(i, j int) bool返回true表示i应该在j前面
  • 反转后的Less(i, j int) bool返回true表示i应该在j后面
  • 只有调用sort.Sort时才会实际执行排序算法

对于自定义类型也是如此:

type Person struct {
    Name string
    Age  int
}

type ByAge []Person

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

func main() {
    people := []Person{
        {"Alice", 25},
        {"Bob", 30},
        {"Charlie", 20},
    }
    
    // 按年龄升序
    sort.Sort(ByAge(people))
    fmt.Println("按年龄升序:", people)
    
    // 按年龄降序
    sort.Sort(sort.Reverse(ByAge(people)))
    fmt.Println("按年龄降序:", people)
}

sort.Reverse的作用就是改变排序的比较逻辑,而sort.Sort才是真正执行排序的算法。

回到顶部