我有一个需要从函数计算的数字列表。我需要计算2百万次。我本可以这样做,但有一种更简单的方法:
def funcx():
return random.random() # for simplicity we use random
top10 = [] # max len = 10
for i in range(2000000):
j = funcx()
top10.append(j)
top10 = sorted(top10, reverse=True)[:10]
答案 0 :(得分:2)
使用固定大小的堆,而不是每次都对列表进行排序:
import heapq
top10=[]
for i in range(2000000):
heapq.heappush(top10, funcx())
top10 = top10[:10]
渐近地,运行时间是相同的,但应该有更少的开销。
另一个选择是使用nsmallest
功能:
heapq.nsmallest(10, (funcx() for i in range(2000000)) )
这比简单地对列表进行排序并返回前10个项目效率低,但它应该(即,我没有检查)使用更少的内存。
答案 1 :(得分:1)
我想使用固定大小的堆显示正确的解决方案(accepted answer 不正确)。
假设您想要 10 个最小的元素。然后您可以使用最大堆并在每次推送后执行弹出。 pop 将删除最大的元素,留下 10 个最小元素的数组。有均匀有效的操作heapq.heappushpop
。 10 个最小元素的代码如下所示:
import heapq
top10 = []
for i in range(2000000):
# Heapq implements min heap, so we need to negate the numbers
heapq.heappushpop(top10, -funcx())
print(top10)
无论如何,这段代码与 heapq.nsmallest
的实现基本相同(它处理一些额外的极端情况,例如 n == 1
),因此您最好使用它:
heapq.nsmallest(10, (funcx() for i in range(2000000)))
或 heap.nlargest
个最大的元素。
答案 2 :(得分:0)
正如另一位用户指出的那样,我还建议实现插入排序。但是,正如您目前所拥有的那样。您只需查找最大值并将其从列表中删除,然后重复10次。
>>> x = [1,2,3,4,5]
>>> max(x)
5
>>> x.remove(5)
>>> max(x)
4