Golang slices.IsSortedFunc
最后修改于 2025 年 4 月 20 日
本教程将解释如何在 Go 中使用 slices.IsSortedFunc 函数。我们将通过实际示例来讲解切片操作以及如何检查排序顺序。
slices.IsSortedFunc 函数用于根据自定义比较函数测试切片是否已排序。它是 Go 实验性 slices 包的一部分。
此函数可用于验证除简单的升序或降序序列之外的自定义排序顺序。如果切片按定义排序,则返回 true。
基本的 slices.IsSortedFunc 示例
slices.IsSortedFunc 最简单的用法是检查数字是否按升序排序。我们定义一个返回 -1、0 或 1 的比较函数。
package main
import (
"cmp"
"fmt"
"slices"
)
func main() {
numbers := []int{1, 2, 3, 4, 5}
isSorted := slices.IsSortedFunc(numbers, func(a, b int) int {
return cmp.Compare(a, b)
})
fmt.Println("Is sorted:", isSorted)
}
我们创建一个已排序的切片,并使用标准比较检查其顺序。由于数字是升序排列的,因此函数返回 true。
检查降序
slices.IsSortedFunc 可通过反转比较逻辑来验证降序。此示例检查数字是否按从高到低的顺序排序。
package main
import (
"cmp"
"fmt"
"slices"
)
func main() {
numbers := []int{5, 4, 3, 2, 1}
isSorted := slices.IsSortedFunc(numbers, func(a, b int) int {
return cmp.Compare(b, a) // Reverse comparison
})
fmt.Println("Is sorted descending:", isSorted)
}
通过将 b 与 a 进行比较而不是将 a 与 b 进行比较,我们反转了排序顺序检查。该函数确认我们的切片已正确按降序排序。
自定义结构排序
我们可以将 slices.IsSortedFunc 与自定义结构类型一起使用。此示例检查人员是否按年龄排序。
package main
import (
"cmp"
"fmt"
"slices"
)
type Person struct {
Name string
Age int
}
func main() {
people := []Person{
{"Alice", 25},
{"Bob", 30},
{"Charlie", 35},
}
isSorted := slices.IsSortedFunc(people, func(a, b Person) int {
return cmp.Compare(a.Age, b.Age)
})
fmt.Println("Sorted by age:", isSorted)
}
比较函数会检查每个 Person 结构的 Age 字段。由于年龄是顺序增加的,因此函数返回 true。
不区分大小写的字符串排序
slices.IsSortedFunc 可以处理不区分大小写的字符串比较。此示例检查单词是否按字母顺序排序,忽略大小写。
package main
import (
"fmt"
"slices"
"strings"
)
func main() {
words := []string{"apple", "Banana", "cherry"}
isSorted := slices.IsSortedFunc(words, func(a, b string) int {
return strings.Compare(strings.ToLower(a), strings.ToLower(b))
})
fmt.Println("Case-insensitive sorted:", isSorted)
}
我们在比较之前将字符串转换为小写,以忽略大小写差异。该函数会确认我们的切片是否按字母顺序排列,而不管大小写。
空切片和单元素切片
slices.IsSortedFunc 对空切片和单元素切片有特殊行为。这些情况始终被视为已排序。
package main
import (
"fmt"
"slices"
)
func main() {
empty := []int{}
single := []string{"hello"}
emptySorted := slices.IsSortedFunc(empty, func(a, b int) int {
return 0 // Doesn't matter
})
singleSorted := slices.IsSortedFunc(single, func(a, b string) int {
return 0 // Doesn't matter
})
fmt.Println("Empty sorted:", emptySorted)
fmt.Println("Single-element sorted:", singleSorted)
}
当元素为零或一个时,没有需要比较的对。根据定义,这些情况下函数返回 true。
复杂的自定义排序
我们可以使用 slices.IsSortedFunc 实现复杂的排序逻辑。此示例检查点是否按与原点的距离排序。
package main
import (
"fmt"
"math"
"slices"
)
type Point struct {
X, Y float64
}
func main() {
points := []Point{
{1, 1},
{2, 2},
{3, 3},
}
isSorted := slices.IsSortedFunc(points, func(a, b Point) int {
distA := math.Sqrt(a.X*a.X + a.Y*a.Y)
distB := math.Sqrt(b.X*b.X + b.Y*b.Y)
if distA < distB {
return -1
} else if distA > distB {
return 1
}
return 0
})
fmt.Println("Sorted by distance:", isSorted)
}
我们在比较之前计算每个点与原点的距离。该函数验证点是否按距离递增排序。
实际示例:版本号
这个实际示例检查版本字符串是否排序正确,并适当处理带有点的数字格式。
package main
import (
"fmt"
"slices"
"strconv"
"strings"
)
func main() {
versions := []string{"1.2", "1.10", "1.9", "2.0"}
isSorted := slices.IsSortedFunc(versions, func(a, b string) int {
aParts := strings.Split(a, ".")
bParts := strings.Split(b, ".")
for i := 0; i < len(aParts) && i < len(bParts); i++ {
aNum, _ := strconv.Atoi(aParts[i])
bNum, _ := strconv.Atoi(bParts[i])
if aNum != bNum {
return aNum - bNum
}
}
return len(aParts) - len(bParts)
})
fmt.Println("Versions sorted correctly:", isSorted)
}
我们将版本字符串拆分为组件并进行数字比较。由于“1.10”应排在“1.9”之后,因此函数返回 false。
来源
本教程通过实际示例涵盖了 Go 中的 slices.IsSortedFunc 函数,演示了如何在各种场景下检查自定义排序顺序。