Golang slices.Sort
最后修改于 2025 年 4 月 20 日
本教程解释了如何在 Go 中使用 slices.Sort 函数。我们将通过不同数据类型的实际示例涵盖排序操作。
slices.Sort 函数按升序对切片元素进行排序。它是 Go 实验性 slices 包的一部分,可与有序类型一起使用。
此函数针对性能进行了优化,并提供了一种便捷的方法来排序集合,而无需为基本情况编写自定义排序逻辑。
基本 slices.Sort 示例
slices.Sort 最简单的用法是按升序对整数切片进行排序。该函数会就地修改原始切片。
package main
import (
"fmt"
"slices"
)
func main() {
numbers := []int{5, 2, 9, 1, 5, 6}
slices.Sort(numbers)
fmt.Println("Sorted numbers:", numbers)
}
我们创建一个无序数字的切片并对它们进行排序。输出显示数字按升序排列。原始切片已被修改。
排序字符串
slices.Sort 可以按字母顺序对字符串切片进行排序。本示例演示了如何对姓名列表进行排序。
package main
import (
"fmt"
"slices"
)
func main() {
names := []string{"Zoe", "Alice", "Bob", "Charlie"}
slices.Sort(names)
fmt.Println("Sorted names:", names)
}
字符串按字典顺序排序。排序区分大小写,在 ASCII 顺序中大写字母排在小写字母之前。
使用自定义比较函数对结构体进行排序
对于自定义类型,我们使用 slices.SortFunc 和一个比较函数。本示例按年龄对人员进行排序。
package main
import (
"cmp"
"fmt"
"slices"
)
type Person struct {
Name string
Age int
}
func main() {
people := []Person{
{"Alice", 25},
{"Bob", 30},
{"Charlie", 20},
}
slices.SortFunc(people, func(a, b Person) int {
return cmp.Compare(a.Age, b.Age)
})
fmt.Println("People sorted by age:", people)
}
我们定义一个使用 cmp.Compare 来确定顺序的比较函数。该函数返回 -1、0 或 1,分别表示小于、等于或大于。
降序排序
要按降序排序,我们会反转比较逻辑。本示例按从高到低的顺序对数字进行排序。
package main
import (
"cmp"
"fmt"
"slices"
)
func main() {
numbers := []int{5, 2, 9, 1, 5, 6}
slices.SortFunc(numbers, func(a, b int) int {
return cmp.Compare(b, a) // Reverse order
})
fmt.Println("Descending order:", numbers)
}
通过比较 b 和 a 而不是 a 和 b,我们反转了排序顺序。对于任何可比较的类型,此技术都适用。
使用多重条件进行排序
复杂的排序可以使用多个字段。本示例按姓氏排序,然后按名字排序。
package main
import (
"cmp"
"fmt"
"slices"
)
type Person struct {
First string
Last string
}
func main() {
people := []Person{
{"Alice", "Smith"},
{"Bob", "Johnson"},
{"Alice", "Johnson"},
}
slices.SortFunc(people, func(a, b Person) int {
if c := cmp.Compare(a.Last, b.Last); c != 0 {
return c
}
return cmp.Compare(a.First, b.First)
})
fmt.Println("Sorted people:", people)
}
比较首先检查姓氏,然后如果姓氏相同,则回退到名字。这会创建自然的排序顺序。
稳定排序
slices.SortStableFunc 维护相等元素的相对顺序。当保留原始顺序很重要时,这很有用。
package main
import (
"cmp"
"fmt"
"slices"
)
type Item struct {
Name string
Order int // Original position
}
func main() {
items := []Item{
{"A", 1},
{"B", 2},
{"A", 3},
}
slices.SortStableFunc(items, func(a, b Item) int {
return cmp.Compare(a.Name, b.Name)
})
fmt.Println("Stable sorted items:", items)
}
两个“A”项都保持了它们原始的相对顺序(1 在 3 之前)。常规排序可能不会为相等元素保留此排序。
性能注意事项
排序函数使用高效的算法。本示例对不同大小的切片进行排序进行基准测试。
package main
import (
"fmt"
"math/rand"
"slices"
"time"
)
func main() {
sizes := []int{100, 10_000, 1_000_000}
for _, size := range sizes {
slice := make([]int, size)
for i := range slice {
slice[i] = rand.Intn(size)
}
start := time.Now()
slices.Sort(slice)
elapsed := time.Since(start)
fmt.Printf("Sorted %d elements in %v\n", size, elapsed)
}
}
该实现对大多数情况使用优化的快速排序。对于最坏情况的输入,性能会下降到 O(n^2),尽管在实践中这种情况很少见。
来源
本教程通过在各种场景下对不同数据类型进行排序的实际示例,介绍了 Go 中的 slices.Sort 函数。