ZetCode

Golang slices.IsSorted

最后修改于 2025 年 4 月 20 日

本教程将介绍如何在 Go 中使用 slices.IsSorted 函数。我们将通过检查排序顺序的实际示例来涵盖切片操作。

slices.IsSorted 函数用于测试切片是否按升序排序。它是 Go 实验性 slices 包的一部分。

此函数对于在执行需要排序输入的预操作之前,验证数据完整性或检查先决条件非常有用。

基本 slices.IsSorted 示例

slices.IsSorted 最简单的用法是检查整数切片是否按升序排序。该函数返回一个布尔结果。

basic_sorted.go
package main

import (
    "fmt"
    "slices"
)

func main() {
    numbers := []int{1, 2, 3, 4, 5}
    unsorted := []int{5, 3, 1, 4, 2}
    
    fmt.Println("Numbers sorted:", slices.IsSorted(numbers))
    fmt.Println("Unsorted sorted:", slices.IsSorted(unsorted))
}

我们创建了两个切片——一个已排序和一个未排序的。该函数通过比较相邻元素来正确识别它们的排序状态。

检查字符串切片

slices.IsSorted 使用字典顺序处理字符串切片。此示例演示了对字符串元素进行的排序检查。

string_sorted.go
package main

import (
    "fmt"
    "slices"
)

func main() {
    words := []string{"apple", "banana", "cherry"}
    mixed := []string{"zebra", "apple", "banana"}
    
    fmt.Println("Words sorted:", slices.IsSorted(words))
    fmt.Println("Mixed sorted:", slices.IsSorted(mixed))
}

字符串使用其 Unicode 码点进行比较。第一个切片顺序正确,而第二个切片未通过排序检查。

使用自定义类型

对于自定义类型,我们必须实现 cmp.Ordered 接口。此示例展示了如何检查结构体切片的排序。

custom_type.go
package main

import (
    "cmp"
    "fmt"
    "slices"
)

type Person struct {
    Name string
    Age  int
}

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

我们使用 slices.IsSortedFunc 和自定义比较函数。该函数检查元素是否按年龄升序排序。

空切片和单元素切片

slices.IsSorted 对于空切片和单元素切片有特殊的行为。根据定义,这两种情况都被认为是已排序的。

edge_cases.go
package main

import (
    "fmt"
    "slices"
)

func main() {
    empty := []int{}
    single := []string{"hello"}
    
    fmt.Println("Empty slice sorted:", slices.IsSorted(empty))
    fmt.Println("Single-element sorted:", slices.IsSorted(single))
}

对于这些边缘情况,该函数返回 true,因为没有元素违反排序顺序。这符合排序的数学定义。

降序检查

要检查降序,我们可以使用 slices.IsSortedFunc 和反向比较。此示例演示了该技术。

descending_order.go
package main

import (
    "cmp"
    "fmt"
    "slices"
)

func main() {
    descending := []int{5, 4, 3, 2, 1}
    ascending := []int{1, 2, 3, 4, 5}
    
    isDescending := slices.IsSortedFunc(descending, func(a, b int) int {
        return cmp.Compare(b, a) // Reverse comparison
    })
    
    fmt.Println("Descending sorted:", isDescending)
    fmt.Println("Ascending as descending:", 
        slices.IsSortedFunc(ascending, func(a, b int) int {
            return cmp.Compare(b, a)
        }))
}

通过比较 b 和 a,而不是 a 和 b,我们有效地检查了降序。第一个切片通过了检查,而第二个切片未通过。

性能注意事项

对于大型切片,slices.IsSorted 非常高效,因为它会在第一个无序元素处停止。此示例演示了其提前终止。

performance.go
package main

import (
    "fmt"
    "slices"
    "time"
)

func main() {
    // Large mostly-sorted slice with one unsorted element at start
    largeSlice := make([]int, 1_000_000)
    for i := range largeSlice {
        largeSlice[i] = i
    }
    largeSlice[0] = 1_000_000 // Make first element out of order
    
    start := time.Now()
    sorted := slices.IsSorted(largeSlice)
    elapsed := time.Since(start)
    
    fmt.Printf("Checked 1M elements in %v\n", elapsed)
    fmt.Println("Slice sorted:", sorted)
}

该函数很快返回,因为它立即找到了无序的元素。这使其对于验证可能未排序的数据非常高效。

实际示例:输入验证

这个实际示例使用 slices.IsSorted 来验证用户输入的数字是否按升序提供。

input_validation.go
package main

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

func main() {
    inputs := []string{"10", "20", "30", "15"}
    
    numbers := make([]int, len(inputs))
    for i, s := range inputs {
        num, err := strconv.Atoi(s)
        if err != nil {
            fmt.Println("Invalid input:", s)
            return
        }
        numbers[i] = num
    }
    
    if slices.IsSorted(numbers) {
        fmt.Println("Inputs are in ascending order")
    } else {
        fmt.Println("Inputs are not properly sorted")
    }
}

我们将字符串转换为整数并验证它们已排序。这展示了应用程序中数据验证的实际用例。

来源

Go 实验性切片包文档

本教程通过各种场景下的排序检查实际示例,介绍了 Go 中的 slices.IsSorted 函数。

作者

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

列出所有 Go 教程