0Pricing
Go Academy · 课时

自定义排序顺序

定义比较函数

自定义排序顺序 是 CoddyKit 上的免费 Go Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Go Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Go Academy 课程共包含 4 节课。

超越默认顺序

默认排序采用升序,但实际数据需要自定义规则:可以按长度、多个字段或计算得到的值排序。

比较函数用于表达您需要的任何规则。

小于函数

sort.Slice 的比较函数签名为 func(i, j int) bool。当元素 i 应排在元素 j 之前时,它会返回 true。

package main

import (
	"fmt"
	"sort"
)

func main() {
	nums := []int{4, 1, 3}
	less := func(i, j int) bool { return nums[i] < nums[j] }
	sort.Slice(nums, less)
	fmt.Println(nums)
}

按字符串长度排序

不要按字母顺序比较,而是比较每个字符串的 len(),从而按长度排序。

package main

import (
	"fmt"
	"sort"
)

func main() {
	words := []string{"pear", "fig", "banana"}
	sort.Slice(words, func(i, j int) bool {
		return len(words[i]) < len(words[j])
	})
	fmt.Println(words)
}

按字段对结构体排序

您可以选择结构体中的任意字段进行比较。这里我们按产品价格排序。

package main

import (
	"fmt"
	"sort"
)

type Product struct {
	Name  string
	Price int
}

func main() {
	items := []Product{{"Pen", 3}, {"Book", 12}, {"Cup", 7}}
	sort.Slice(items, func(i, j int) bool {
		return items[i].Price < items[j].Price
	})
	fmt.Println(items)
}

多字段排序

如果第一个字段相等,可以比较第二个字段来打破平局。先按年龄排序,再按姓名排序。

package main

import (
	"fmt"
	"sort"
)

type Person struct {
	Name string
	Age  int
}

func main() {
	p := []Person{{"Zoe", 30}, {"Ann", 30}, {"Bob", 25}}
	sort.Slice(p, func(i, j int) bool {
		if p[i].Age != p[j].Age {
			return p[i].Age < p[j].Age
		}
		return p[i].Name < p[j].Name
	})
	fmt.Println(p)
}

使用 sort.Reverse 反转顺序

sort.Reverse 会包装一个 sort.Interface,以反转其顺序。它可以与 sort.IntSlice 等辅助类型配合使用。

package main

import (
	"fmt"
	"sort"
)

func main() {
	nums := []int{1, 4, 2, 3}
	sort.Sort(sort.Reverse(sort.IntSlice(nums)))
	fmt.Println(nums)
}

sort.Interface

如果需要完全控制排序过程,请实现 sort.Interface:包含三个方法 Len()、Less(i, j int) bool 和 Swap(i, j int)。

package main

import (
	"fmt"
	"sort"
)

type ByLen []string

func (s ByLen) Len() int           { return len(s) }
func (s ByLen) Less(i, j int) bool { return len(s[i]) < len(s[j]) }
func (s ByLen) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }

func main() {
	w := []string{"ccc", "a", "bb"}
	sort.Sort(ByLen(w))
	fmt.Println(w)
}

按计算值排序

比较过程可以使用任意表达式。例如,可以按照数字距离零的绝对距离进行排序。

package main

import (
	"fmt"
	"sort"
)

func abs(n int) int {
	if n < 0 {
		return -n
	}
	return n
}

func main() {
	nums := []int{-5, 2, -1, 3}
	sort.Slice(nums, func(i, j int) bool {
		return abs(nums[i]) < abs(nums[j])
	})
	fmt.Println(nums)
}

不区分大小写排序

在比较过程中使用 strings.ToLower,即可在排列字符串时忽略大小写。

package main

import (
	"fmt"
	"sort"
	"strings"
)

func main() {
	w := []string{"banana", "Apple", "cherry"}
	sort.Slice(w, func(i, j int) bool {
		return strings.ToLower(w[i]) < strings.ToLower(w[j])
	})
	fmt.Println(w)
}

切片与接口

有两种方式可以自定义顺序:

  • sort.Slice - 快速使用内联小于函数
  • sort.Interface - 使用包含三个方法的可复用命名类型

对于一次性排序,请优先使用 sort.Slice。

保持比较函数纯粹

比较函数应该只读取元素并返回布尔值。它不能修改切片或产生副作用,否则排序行为可能不可预测。

快速检查

您想按年龄对人员排序,并在年龄相同时按姓名排序。应使用什么技术?

回顾

您可以定义任意排序顺序:

  • 小于函数用于表达您的规则
  • 多字段排序会在出现平局时比较第二个字段
  • sort.Reverse 会反转顺序;sort.Interface 提供可复用的类型

常见问题解答

「自定义排序顺序」课时是免费的吗?

是的 — 「自定义排序顺序」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Go Academy 课程的其余内容,请升级到 CoddyKit PRO。 Go Academy 课程共包含 4 节课。

「自定义排序顺序」这节课中我会学到什么?

定义比较函数 你通过在浏览器中直接运行的动手代码来练习 Go Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Go Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Go Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。

「自定义排序顺序」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Go Academy 课中编写并运行代码吗?

能。每节 Go Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 切片排序
  2. 自定义排序顺序
  3. 搜索已排序数据
  4. 稳定排序
← 返回 Go Academy