Golang slices.BinarySearchFunc
最后修改于 2025 年 4 月 20 日
本教程将介绍如何在 Go 语言中使用 slices.BinarySearchFunc
函数。我们将涵盖使用自定义比较函数进行二分查找操作。
slices.BinarySearchFunc
函数在已排序的 slice 上执行二分查找。它使用自定义比较函数来确定元素的排序。
此函数对于在大型已排序集合中进行搜索非常高效。它会返回目标值在保持顺序的情况下应该插入的位置。
基本的 BinarySearchFunc 示例
最简单的用法是在已排序的 slice 中搜索数字。我们定义一个返回 -1、0 或 1 的比较函数。
package main import ( "fmt" "slices" ) func main() { numbers := []int{1, 3, 5, 7, 9} cmp := func(a, b int) int { if a == b { return 0 } else if a < b { return -1 } return 1 } pos, found := slices.BinarySearchFunc(numbers, 5, cmp) fmt.Printf("Position: %d, Found: %v\n", pos, found) }
比较函数遵循标准的排序规则。搜索在 slice 的第 2 个位置找到值 5。
搜索字符串
slices.BinarySearchFunc
可以搜索字符串 slice。此示例执行不区分大小写的字符串比较。
package main import ( "fmt" "slices" "strings" ) func main() { words := []string{"apple", "Banana", "cherry", "Date"} cmp := func(a, b string) int { aLower := strings.ToLower(a) bLower := strings.ToLower(b) switch { case aLower == bLower: return 0 case aLower < bLower: return -1 default: return 1 } } pos, found := slices.BinarySearchFunc(words, "banana", cmp) fmt.Printf("Position: %d, Found: %v\n", pos, found) }
比较函数首先将字符串转换为小写。这使得在查找“Banana”时搜索不区分大小写。
按字段搜索结构体
我们可以按特定字段搜索结构体 slice。此示例按年龄搜索人员。
package main import ( "fmt" "slices" ) type Person struct { Name string Age int } func main() { people := []Person{ {"Alice", 25}, {"Bob", 30}, {"Charlie", 35}, } cmp := func(p Person, age int) int { switch { case p.Age == age: return 0 case p.Age < age: return -1 default: return 1 } } pos, found := slices.BinarySearchFunc(people, 30, cmp) fmt.Printf("Position: %d, Found: %v\n", pos, found) }
比较函数会比较 Person 结构体的 Age 字段。它在第 1 个位置找到 Bob,他的年龄正好是 30 岁。
自定义排序
BinarySearchFunc 支持自定义排序方案。此示例按降序搜索。
package main import ( "fmt" "slices" ) func main() { numbers := []int{9, 7, 5, 3, 1} // Descending order cmp := func(a, b int) int { if a == b { return 0 } else if a > b { // Note: reversed comparison return -1 } return 1 } pos, found := slices.BinarySearchFunc(numbers, 5, cmp) fmt.Printf("Position: %d, Found: %v\n", pos, found) }
比较函数会颠倒标准的排序逻辑。这允许在降序排序的 slice 中进行搜索。
带有部分匹配的搜索
我们可以在比较中实现部分匹配。此示例在字符串 slice 中搜索前缀。
package main import ( "fmt" "slices" "strings" ) func main() { words := []string{"apple", "application", "banana", "book"} cmp := func(s, prefix string) int { if strings.HasPrefix(s, prefix) { return 0 } else if s < prefix { return -1 } return 1 } pos, found := slices.BinarySearchFunc(words, "app", cmp) fmt.Printf("Position: %d, Found: %v\n", pos, found) }
比较使用 strings.HasPrefix 检查前缀匹配。它找到“app”的匹配项“apple”和“application”。
处理未找到的情况
当未找到目标时,该函数返回插入位置。此示例演示了如何处理缺失的元素。
package main import ( "fmt" "slices" ) func main() { numbers := []int{10, 20, 30, 40, 50} cmp := func(a, b int) int { if a == b { return 0 } else if a < b { return -1 } return 1 } pos, found := slices.BinarySearchFunc(numbers, 25, cmp) if found { fmt.Println("Found at position", pos) } else { fmt.Printf("Not found, would insert at %d\n", pos) } }
值 25 不在 slice 中,但将被插入到第 2 个位置。这会保持 slice 的排序顺序。
实际示例:字典查找
这个实际示例实现了字典查找。它在一个已排序的 slice 中搜索单词定义。
package main import ( "fmt" "slices" ) type Entry struct { Word string Definition string } func main() { dictionary := []Entry{ {"apple", "A fruit"}, {"banana", "Yellow fruit"}, {"cherry", "Small red fruit"}, } cmp := func(e Entry, word string) int { switch { case e.Word == word: return 0 case e.Word < word: return -1 default: return 1 } } pos, found := slices.BinarySearchFunc(dictionary, "banana", cmp) if found { fmt.Println("Definition:", dictionary[pos].Definition) } else { fmt.Println("Word not found") } }
比较函数按 Word 字段匹配 Entry 结构体。它有效地在已排序的字典 slice 中查找定义。
来源
本教程介绍了 Go 语言中的 slices.BinarySearchFunc
函数。我们通过自定义比较函数探索了各种搜索场景。