您的当前位置:首页正文

python如何在list中找Topk的数值和索引

来源:好兔宠物网
python如何在list中找Topk的数值和索引

需求:

对于⼀个python list 或者numpy数组,我需要找到这个list中最⼤的K个数及其对应的下标。

解决⽅式:

1. 可以构造字典通过排序解决,不过代码量较多。2. 使⽤heapq库,可以直接获取最⼤值的下标和数值。

import heapqa = [4,2,6,1,9,9]

# 获取下标, 输出为[4, 5, 2]

heapq.nlargest(3, range(len(a)), a.__getitem__)

# 获取数值, 输出为[9, 9, 6]heapq.nlargest(3,a)

如果要取最⼩的数,使⽤ nsmallest即可补充:Python 利⽤中间值求TopK 算法

算法思想

⾸先我们要思考,我要做什么?解决什么问题?

TopK问题,找出⼀组数据中的前K个最⼤值或者最⼩值,这个数据是否重复?要做去重处理?ok 我们明确我们做什么了 ,那介绍的python处理的topK 算法过程是怎么样的呢?

如果⽤排序那就没必要引⼊topK 了,当数据强⼤的时候选取TopK 可以省略很多排序的计算,⾄于有多优化⾃⼰去思考下,就⽐如排列组合的C,A的区别,⼀个是抽取,⼀个是抽取并排列…

以下以找出TopK 的最⼤值为例,最⼩值的可以⾃⼰修改⼀下下就可以

介绍的算法思想是利⽤中间值,将数列分为三部分 ,【⽐中间值⼤的列表】,中间值,【⽐中间值⼩的列表】那么我们当⽐较

【⽐中间值⼤的列表】的个数 == k的时候就可以得出前K个最⼤值了,因此

重点就是找出这个中间值

如何找出中间值

以列表的第⼀个数开始为中间值,拆分为三部分

if 【⽐中间值⼤的列表】的个数 == k:return 中间值 #程序出⼝,结束。if 【⽐中间值⼤的列表】的个数 < k :·····继续在【⽐中间值⼩的列表】找·····K - 【⽐中间值⼤的列表】的个数 -1 个数

(为什么要减⼀,1是前⼀次的中间值,分的三部分,前部分后部分都没有包含中间值,因此…)if 【⽐中间值⼤的列表】的个数 > k :

…也就是说⽐中间值⼤的列表⽐K还⼤,那就在这个列表中继续找就⾏

结合代码和注释看

如果要找最⼩值,只需要改⼀下就ok ,还可以设置⼀个布尔值的输⼊,来做前K个最⼤值最⼩值

#2019 11 04

#author 半⽄地⽠烧

#TopK 算法,找出序列中前K个最⼤值的#输⼊⼀个seq

# 输出以seq[0]为中间值 划分的三个部分,中间值,⽐这个值⼤的seq ,⽐这个值⼩的seq,# 即splitNum,theBig,theSmalldef Split_Seq(seq): splitNum = seq[0]

seq = seq[1:]#两个部分都不包含中间值,因此切⽚去除seq[0] theBig = [x for x in seq if x >= splitNum] theSmall = [x for x in seq if x < splitNum] return splitNum,theBig,theSmall#找出中间值

def topKNum(seq,k):

splitNum, theBig, theSmall = Split_Seq(seq) theBigLen = len(theBig)

if k == theBigLen:

return splitNum#出⼝,返回这个中间值,

# 为什么不直接返回thebig?因为存在递归的原因thebig 不是在初始的seq找出来的 #需要重新Split,即可,读者⾃⼰思考 # ⼤值的列表中还未够K个数的情况, if k > theBigLen:

return topKNum(theSmall,k-theBigLen-1) # ⼤值的列表中⼤于K个数的情况 return topKNum(theBig,k)#由中间值找出TopK个值,def getTopK(seq,k):

return [i for i in seq if i > topKNum(seq, k)]if __name__ == '__main__':

alist = [7, 3, 5, 1,885,234,2211,222,22, 2, 11, 2, 115]

print(\"===为了验证,引⼊排序观看===\ print(getTopK(alist, 3))

以上为个⼈经验,希望能给⼤家⼀个参考,也希望⼤家多多⽀持。

因篇幅问题不能全部显示,请点此查看更多更全内容