sort.Interface
本课属于 Coddy GO 学习旅程的“面向对象编程”单元。第 74 课,共 107 课。
sort 包提供了另一个接口设计的绝佳示例。要对自定义集合排序,你的类型必须实现 sort.Interface:
type Interface interface {
Len() int
Less(i, j int) bool
Swap(i, j int)
}这三个方法为排序算法提供了所需的一切:集合的长度、比较元素的方法,以及交换元素的方法。下面介绍如何让自定义结构体组成的切片支持排序:
type Person struct {
Name string
Age int
}
type ByAge []Person
func (a ByAge) Len() int { return len(a) }
func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }
func (a ByAge) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func main() {
people := []Person{
{"Alice", 30},
{"Bob", 25},
{"Carol", 35},
}
sort.Sort(ByAge(people))
fmt.Println(people)
// [{Bob 25} {Alice 30} {Carol 35}]
}关键在于基于你的切片创建一个命名类型(ByAge)。这样,你就可以为同一份数据定义不同的排序行为。你也可以通过不同的 Less 实现创建 ByName,以便按字母顺序排序。
只要你的类型满足 sort.Interface,就能自动与 sort.Sort()、sort.Reverse() 和 sort.IsSorted() 配合使用。
挑战
简单让我们构建一个可排序的产品库存系统,展示 Go 的 sort.Interface 的强大功能!你将创建一个 Product 类型,并实现多种排序策略,让同一组产品可以按不同方式排序。
你需要将代码组织在两个文件中:
product.go:定义产品类型和排序实现。创建一个
Product结构体,包含三个字段:Name(字符串)、Price(float64)和Quantity(int)。基于
[]Product创建两个命名类型:ByPrice:按价格升序排列产品ByQuantity:按数量降序排列产品(数量最多的排在最前面)
每个类型都需要实现
sort.Interface要求的三个方法:Len()、Less(i, j int)和Swap(i, j int)。Less方法用于确定每种类型的排序顺序。main.go:构建并排序产品库存。读取排序模式(
price或quantity),然后读取产品数量,接着读取产品详情。每个产品占三行,分别是名称、价格和数量。创建产品切片,根据排序模式使用相应的排序类型对产品进行排序,然后按以下格式打印每个产品:
[Name]: $[Price] (x[Quantity])价格显示为两位小数。
输入内容如下:
- 第 1 行:排序模式(
price或quantity) - 第 2 行:产品数量
- 后续各行:产品详情(名称、价格、数量,每个产品占三行)
例如,给定以下输入:
price
3
Laptop
999.99
5
Mouse
29.99
50
Keyboard
79.99
25输出应为:
Mouse: $29.99 (x50)
Keyboard: $79.99 (x25)
Laptop: $999.99 (x5)再例如,给定以下输入:
quantity
3
Laptop
999.99
5
Mouse
29.99
50
Keyboard
79.99
25输出应为:
Mouse: $29.99 (x50)
Keyboard: $79.99 (x25)
Laptop: $999.99 (x5)请注意,只需使用不同的命名类型,相同的产品数据就能按不同方式排序。只要你的类型满足 sort.Interface,就可以与标准库中的 sort.Sort() 无缝配合。
亲手试试
package main
import (
"bufio"
"fmt"
"os"
"sort"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// 读取排序模式
var mode string
fmt.Fscanln(reader, &mode)
// 读取商品数量
var count int
fmt.Fscanln(reader, &count)
// 读取商品信息
products := make([]Product, count)
for i := 0; i < count; i++ {
name, _ := reader.ReadString('\n')
name = strings.TrimSpace(name)
priceStr, _ := reader.ReadString('\n')
priceStr = strings.TrimSpace(priceStr)
price, _ := strconv.ParseFloat(priceStr, 64)
qtyStr, _ := reader.ReadString('\n')
qtyStr = strings.TrimSpace(qtyStr)
quantity, _ := strconv.Atoi(qtyStr)
products[i] = Product{Name: name, Price: price, Quantity: quantity}
}
// TODO:根据 mode 对商品排序
// 如果 mode 是 "price",使用 ByPrice 类型
// 如果 mode 是 "quantity",使用 ByQuantity 类型
// 使用 sort.Sort() 和对应的类型进行排序
// TODO:按以下格式输出每件商品:
// [Name]: $[Price] (x[Quantity])
// 使用 fmt.Printf,并用 %.2f 格式化价格
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Go 在线编译器