ZetCode

Golang slices.IsSortedFunc

最后修改于 2025 年 4 月 20 日

本教程将解释如何在 Go 中使用 slices.IsSortedFunc 函数。我们将通过实际示例来讲解切片操作以及如何检查排序顺序。

slices.IsSortedFunc 函数用于根据自定义比较函数测试切片是否已排序。它是 Go 实验性 slices 包的一部分。

此函数可用于验证除简单的升序或降序序列之外的自定义排序顺序。如果切片按定义排序,则返回 true。

基本的 slices.IsSortedFunc 示例

slices.IsSortedFunc 最简单的用法是检查数字是否按升序排序。我们定义一个返回 -1、0 或 1 的比较函数。

basic_sorted.go
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 可通过反转比较逻辑来验证降序。此示例检查数字是否按从高到低的顺序排序。

descending_order.go
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 与自定义结构类型一起使用。此示例检查人员是否按年龄排序。

struct_sorting.go
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 可以处理不区分大小写的字符串比较。此示例检查单词是否按字母顺序排序,忽略大小写。

case_insensitive.go
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 对空切片和单元素切片有特殊行为。这些情况始终被视为已排序。

empty_slice.go
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 实现复杂的排序逻辑。此示例检查点是否按与原点的距离排序。

complex_sorting.go
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)
}

我们在比较之前计算每个点与原点的距离。该函数验证点是否按距离递增排序。

实际示例:版本号

这个实际示例检查版本字符串是否排序正确,并适当处理带有点的数字格式。

version_sorting.go
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 实验性切片包文档

本教程通过实际示例涵盖了 Go 中的 slices.IsSortedFunc 函数,演示了如何在各种场景下检查自定义排序顺序。

作者

我的名字是 Jan Bodnar,我是一名充满热情的程序员,拥有丰富的编程经验。自 2007 年以来,我一直在撰写编程文章。迄今为止,我已撰写了 1,400 多篇文章和 8 本电子书。我在教授编程方面拥有十多年的经验。

列出所有 Go 教程