← 中文资源

简体中文版本

用堆选择 Top-K

借助 heapq.nlargest 与 nsmallest 只保留 K 个候选,内存占用与 K 成正比,并在分数相同时按名称排序保证输出稳定。

阅读英文原文

功能说明

top_k 在流式数据上选出分数最高或最低的 K 条记录。它调用 heapq.nlargest 或 nsmallest,内部只维护大小为 K 的堆,因此内存占用与 K 成正比,而不是与输入规模成正比。选出候选后再按分数排序,分数相同时按名称升序排列,保证输出稳定、可测试。

关键代码

select = heapq.nlargest if largest else heapq.nsmallest
chosen = select(k, records, key=lambda record: record.score)
chosen.sort(
    key=lambda record: (-record.score, record.name)
    if largest
    else (record.score, record.name),
)

key 只返回分数,因此边界上的同分记录由 heapq 按输入顺序稳定选择;最终排序再统一同分顺序。

使用注意

  • k 为 0 返回空列表,负数直接报错。
  • 输入可以是任意可迭代对象,不必先转成列表,适合逐行读取的大文件。
  • 同分记录在截断边界上取决于输入顺序;若业务要求固定优先级,应把名称等次级键放进 key。
  • nlargest 仍需要遍历全部输入,时间复杂度是 O(n log k),不是 O(k)。
  • 返回的是原 Record 对象引用,修改它们会影响源数据。

验证方式

示例输出最高分三名应为 alpha、echo、delta,最低分三名应为 bravo、charlie、delta。可以增加同分记录并打乱输入顺序,观察边界选择与最终排序的差异。