排序切片的任意类型
【摘要】 1 简介Go sort 包的排序方法概述。Go 的排序主要由 sort 包提供,核心概念是 sort.Interface:type Interface interface { Len() int Less(i, j int) bool Swap(i, j int)}基于这个接口,Go 提供了三类排序方法: 2 面向基础类型的排序(已封装)Go 内置以下封装好的排序函数: ...
1 简介
Go sort 包的排序方法概述。

Go 的排序主要由 sort 包提供,核心概念是 sort.Interface:
type Interface interface {
Len() int
Less(i, j int) bool
Swap(i, j int)
}
基于这个接口,Go 提供了三类排序方法:
2 面向基础类型的排序(已封装)
Go 内置以下封装好的排序函数:
sort.Ints([]int)
sort.Float64s([]float64)
sort.Strings([]string)
以及对应的返回是否有序的检查:
sort.IntsAreSorted()
sort.Float64sAreSorted()
sort.StringsAreSorted()
int 排序
ints := []int{3, 1, 2}
sort.Ints(ints)
float 排序
floats := []float64{1.2, 3.4, -2.0}
sort.Float64s(floats)
string 排序(UTF-8 字符序)
Go 的 string 排序按「字节序/Unicode 编码点序」排序,即 UTF-8 lexicographical 排序。
对英文和 ASCII 字符效果符合直觉,但对中文是 按 Unicode 编码排序,不是按拼音或笔画排序。
strs := []string{"中国", "美国", "日本"}
sort.Strings(strs)
实际排序结果可能是:[“中国”, “日本”, “美国”](按 Unicode)
2 排序函数(更灵活) sort.Slice / sort.SliceStable
Go 1.8 之后推荐使用:
sort.Slice(slice, func(i, j int) bool {
return slice[i].Field < slice[j].Field
})
稳定排序:
sort.SliceStable(slice, func(i, j int) bool {
return slice[i].Field < slice[j].Field
})
适用于切片中存放自定义 struct 的场景。
- 完整实现 sort.Interface 例子
实现以下三个方法即可:
Len()
Less(i,j)
Swap(i,j)
适用:
需要高级排序规则(多字段排序、动态组合规则等)。
3 按拼音进行排序
最常用、最简洁的 Go 内置 sort 包 + 第三方拼音库 实现 “按中文拼音排序” 的完整示例。
这里使用社区中最常用的拼音库:
github.com/mozillazg/go-pinyin
示例:使用 sort.Slice + pinyin 按中文拼音排序
-
-
安装第三方拼音包
go get github.com/mozillazg/go-pinyin
-
-
-
示例代码
import ( "fmt" "sort" "github.com/mozillazg/go-pinyin" ) func main() { names := []string{"张三", "李四", "王五", "赵六", "陈七", "欧阳修"} // 配置拼音风格 a := pinyin.NewArgs() a.Style = pinyin.Normal // 普通风格,不带声调 sort.Slice(names, func(i, j int) bool { // 转拼音(返回二维数组,每个汉字可能对应多个音) pi := pinyin.Pinyin(names[i], a) pj := pinyin.Pinyin(names[j], a) // 把二维数组转成可比较的拼音字符串 si := flattenPinyin(pi) sj := flattenPinyin(pj) return si < sj }) fmt.Println(names) } // 拼音二维数组转为字符串(欧阳 → ou yang) func flattenPinyin(py [][]string) string { res := "" for _, p := range py { if len(p) > 0 { res += p[0] } } return res }
-
-
- 运行结果(示例)
排序前:
[张三 李四 王五 赵六 陈七 欧阳修]
按拼音排序后:
[陈七 李四 欧阳修 王五 张三 赵六]
拼音对照:
名字 拼音
陈七 chenqi
李四 lisi
欧阳修 ouyangxiu
王五 wangwu
张三 zhangsan
赵六 zhaoliu
排序结果完全符合拼音顺序。
4 更常用 Struct 字段排序的版本
如果你有一个 struct,例如:
type Person struct {
Name string
Age int
}
按 Name 的中文拼音排序:
sort.Slice(people, func(i, j int) bool {
pi := flattenPinyin(pinyin.Pinyin(people[i].Name, a))
pj := flattenPinyin(pinyin.Pinyin(people[j].Name, a))
return pi < pj
})
- 提升性能(避免每次都重新转拼音)
拼音转换成本较高,如果列表很大(几万条以上),最好 提前缓存拼音:
type Person struct {
Name string
PinyinKey string // 缓存拼音
}
func preprocessPinyin(p *Person) {
a := pinyin.NewArgs()
a.Style = pinyin.Normal
p.PinyinKey = flattenPinyin(pinyin.Pinyin(p.Name, a))
}
排序时只比较 PinyinKey:
sort.Slice(people, func(i, j int) bool {
return people[i].PinyinKey < people[j].PinyinKey
})
效率可以提升数倍。
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)