当前位置:首页 > 文章列表 > Golang > Go教程 > Go slices.BinarySearchFunc 怎样在自定义顺序中查找

Go slices.BinarySearchFunc 怎样在自定义顺序中查找

来源:17golang原创 2026-10-26 13:30:44 0浏览 收藏

在自定义顺序中使用 slices.BinarySearchFunc,关键是让切片现有顺序与查询比较器保持一致。比较器的负数表示元素排在目标之前,零表示匹配,正数表示排在目标之后。分数降序也可以查,只需按降序解释先后关系,而不能沿用普通升序的比较器。

官方地址:https://pkg.go.dev/slices

把漏查现象缩小到排序规则

设想一个榜单:原来按分数升序排列,后来展示需求改成降序,但查询代码仍按升序比较。这时“列表里明明有这个分数却找不到”并不能证明二分搜索有问题,首先应该对照两处比较规则。这里是用于解释问题的假设案例,不是线上事故记录。

这个问题通常在排序方向调整之后出现:展示顺序改变,搜索条件没有同步。二分搜索依赖有序分区,不会替调用方重新排序,也不会自动识别降序。只检查元素是否存在,而不检查其排序规则,会漏掉真正的触发条件。

统一排序与查询的比较语义

把分数比较封装成 scoreOrder。它对两个分数定义同一个顺序,再分别供排序比较器和查询比较器调用。对于降序,较高分数在目标之前,因此应返回负数。比如目标是84,95在它之前,72在它之后。

比较结果在当前自定义顺序中的含义降序分数示例,目标84
负数元素在目标之前95
零按查询键匹配84
正数元素在目标之后72
排序和查找共享分数比较规则的静态结构图
静态结构图:排序边界和查询边界共同依赖scoreOrder;连线表达依赖关系,不代表执行时间线。

用结构体切片查找整数键

下面的独立示例使用Entry保存名称和分数,查询目标直接传整数。查询比较器接收一个Entry和一个整数,说明元素类型与目标类型可以不同,不需要为了查分数而临时构造完整对象。

package main

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

type Entry struct {
    Name string
    Score int
}

// 按分数降序定义先后,避免用减法比较引入溢出。
func scoreOrder(a, b int) int {
    return cmp.Compare(b, a)
}

func main() {
    rows := []Entry{{"青禾", 72}, {"远山", 95}, {"白露", 84}, {"溪石", 84}}
    // 排序和搜索都依赖 scoreOrder,不能一边降序一边升序。
    slices.SortFunc(rows, func(a, b Entry) int {
        return scoreOrder(a.Score, b.Score)
    })
    byScore := func(e Entry, target int) int {
        return scoreOrder(e.Score, target)
    }
    for _, target := range []int{84, 90, 60} {
        i, found := slices.BinarySearchFunc(rows, target, byScore)
        // 只有 found 为真才能把 i 当成命中元素下标。
        if found {
            fmt.Printf("分数=%d 下标=%d 命中分数=%d\n", target, i, rows[i].Score)
        } else {
            fmt.Printf("分数=%d 插入位置=%d\n", target, i)
        }
    }
}

按代码语义推导,分数排序为95、84、84、72;搜索84得到下标1且匹配为真,搜索90得到插入位置1,搜索60得到插入位置4。以上是示例的预期行为,未将它描述为本机执行日志。SortFunc不保证相等元素的原有相对次序,因此不能据此指定两个84分对象中的某个名称必然先出现。

解释首个匹配和插入位置

返回值由位置i与布尔值found组成。存在多个比较结果为零的元素时,返回最早匹配的位置;这个“匹配”由比较器决定,在示例里只表示分数相等,不表示名称也相同。未命中时,i表示保持当前顺序的插入位置,可能等于切片长度,不能直接访问rows[i]。

如果需要按“分数降序、名称升序”精确定位一个对象,排序器和查找器都应实现这一组合顺序,并让目标包含两个字段。若只是按分数定位同分组的起点,按分数降序且同分连续即可;定位后要取得整个同分组,可以从起点向后读取,直到分数不同或到达末尾。

查询目标、位置和匹配状态的静态关系图
静态结构图:整数目标通过查询比较器关联Entry.Score;位置与匹配状态分别描述返回值,匹配后才允许把位置用于读取元素。

空切片与nil切片都没有命中元素,返回位置0与false。查找本身不插入元素;若以后用这个位置插入新记录,还要遵守完整排序规则,尤其要考虑同分时名称等次级字段。

避免后续修改破坏顺序

修复比较器之后,还要把排序前提留在维护代码旁边。更改某条记录的Score、直接追加新记录或切换排序键,都可能破坏有序条件。更新之后应按相同顺序维护位置,或在重新排序之后再查。比较器应保持稳定,不能依赖会在查找期间改变的外部状态。

排查时可用IsSortedFunc配合同一个排序比较器帮助观察顺序,但不需要每次查询都做一次全表扫描。二分查找的比较次数随长度按对数增长;若每次查询前都重新排序,整体成本就包括排序,不能把整个业务操作都称为一次对数查找。

为什么比较器不直接返回分数相减?

大整数相减可能溢出,破坏符号判断。示例使用cmp.Compare并交换参数表达降序,使先后规则更清楚。

返回false是不是说明位置没有意义?

不是。位置仍表示目标在自定义顺序中的插入点,只是不能把它解释成已存在记录的下标。

能按名称搜索只按分数排序的切片吗?

通常不能。名称匹配需要满足名称比较器要求的顺序;换查询字段不会自动建立新的有序关系。

维护这段代码时,优先确认排序键、方向与比较器符号是否一致,再分别处理命中与插入位置。这比只围绕某个漏查目标修改条件更能避免同类问题反复出现。

参考:https://pkg.go.dev/slices#BinarySearchFunc

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Go maps.All 怎样用迭代器遍历 map 的键值对Go maps.All 怎样用迭代器遍历 map 的键值对
上一篇
Go maps.All 怎样用迭代器遍历 map 的键值对
Go netip.Addr.As16 怎样转换成固定长度地址字节
下一篇
Go netip.Addr.As16 怎样转换成固定长度地址字节
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    704次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    712次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    789次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    749次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    583次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码