ZetCode

Golang slices.SortedFunc

最后修改于 2025 年 4 月 20 日

本教程将解释如何在 Go 中使用 slices.SortedFunc 函数。我们将通过实际示例介绍自定义排序检查。

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

当您需要验证超出基本升序/降序检查的排序顺序时,此函数非常有用。如果切片已排序,它将返回 true。

基本的 slices.SortedFunc 示例

slices.SortedFunc 最简单的用法是检查数字是否按升序排序。我们为整数定义了一个比较函数。

basic_sorted.go
package main

import (
    "fmt"
    "slices"
)

func main() {
    numbers := []int{1, 2, 3, 4, 5}
    
    isSorted := slices.SortedFunc(numbers, func(a, b int) int {
        return a - b
    })
    
    fmt.Println("Numbers sorted:", isSorted)
}

比较函数根据 a 是否应排在 b 之前、等于或之后返回负值、零或正值。切片已排序。

检查降序

slices.SortedFunc 通过反转比较逻辑来验证降序。此示例检查数字是否按从高到低的顺序排序。

descending_order.go
package main

import (
    "fmt"
    "slices"
)

func main() {
    numbers := []int{5, 4, 3, 2, 1}
    
    isSorted := slices.SortedFunc(numbers, func(a, b int) int {
        return b - a
    })
    
    fmt.Println("Numbers sorted descending:", isSorted)
}

通过将 a 减去 b 而不是 b 减去 a,我们反转了排序顺序检查。对于正确排序的降序序列,该函数返回 true。

按长度对字符串进行排序

我们可以将 slices.SortedFunc 与自定义标准一起使用。此示例检查字符串是否按长度排序。

string_length.go
package main

import (
    "fmt"
    "slices"
)

func main() {
    words := []string{"a", "bb", "ccc", "dddd"}
    
    isSorted := slices.SortedFunc(words, func(a, b string) int {
        return len(a) - len(b)
    })
    
    fmt.Println("Words sorted by length:", isSorted)
}

比较函数使用字符串长度而不是字典顺序。这展示了超出默认比较的自定义排序标准。

使用结构体

slices.SortedFunc 可与自定义结构体类型一起使用。此示例检查人员是否按年龄排序。

struct_sorting.go
package main

import (
    "fmt"
    "slices"
)

type Person struct {
    Name string
    Age  int
}

func main() {
    people := []Person{
        {"Alice", 25},
        {"Bob", 30},
        {"Charlie", 35},
    }
    
    isSorted := slices.SortedFunc(people, func(a, b Person) int {
        return a.Age - b.Age
    })
    
    fmt.Println("People sorted by age:", isSorted)
}

比较函数访问每个 Person 结构体的 Age 字段。当年龄按升序排列时,切片被视为已排序。

不区分大小写的字符串排序

此示例使用 slices.SortedFunc 和字符串演示了不区分大小写的排序验证。

case_insensitive.go
package main

import (
    "fmt"
    "slices"
    "strings"
)

func main() {
    words := []string{"apple", "Banana", "cherry", "Date"}
    
    isSorted := slices.SortedFunc(words, func(a, b string) int {
        return strings.Compare(strings.ToLower(a), strings.ToLower(b))
    })
    
    fmt.Println("Case-insensitive sorted:", isSorted)
}

通过在比较前将字符串转换为小写,我们可以忽略大小写差异。该函数检查单词是否按字母顺序排序,忽略大小写。

空切片和单元素切片

slices.SortedFunc 对空切片和单元素切片有特殊行为。这些情况始终被视为已排序。

edge_cases.go
package main

import (
    "fmt"
    "slices"
)

func main() {
    empty := []int{}
    single := []string{"alone"}
    
    emptySorted := slices.SortedFunc(empty, func(a, b int) int {
        return a - b
    })
    
    singleSorted := slices.SortedFunc(single, func(a, b string) int {
        return len(a) - len(b)
    })
    
    fmt.Println("Empty sorted:", emptySorted)
    fmt.Println("Single element sorted:", singleSorted)
}

当元素为零或一个时,没有需要比较的,因此函数返回 true。这符合排序的数学定义。

实际示例:版本排序

此实际示例检查版本字符串是否正确排序,并处理数字和字典组件。

version_sorting.go
package main

import (
    "fmt"
    "slices"
    "strconv"
    "strings"
)

func main() {
    versions := []string{"1.2", "1.10", "1.9", "2.0", "0.5"}
    
    isSorted := slices.SortedFunc(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:", isSorted)
}

比较函数拆分版本字符串并按数字比较组件。这展示了复杂的实际排序验证。

来源

Go 实验性切片包文档

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

作者

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

列出所有 Go 教程