Skip to main content
 首页 » 编程设计

python之组合和排序元组列表的最快方法是什么

2025年05月04日16dyllove98

我有一个元组列表列表。每个元组的形式都是(string,int),例如

lst = list() 
lst.append([('a',5),('c',10),('d',3),('b',1)]) 
lst.append([('c',14),('f',4),('b',1)]) 
lst.append([('d',22),('f',2)]) 

将 int 视为不同文本 block 中每个字符串的计数。

我需要做的是生成前 N 出现的字符串及其累积计数的列表。所以在上面的例子中,a出现了5次,b出现了两次,c出现了24次等等。如果N=2,那么我将不得不生成一对并行列表 ['d','c'] 和 [25,24] 或一个元组列表[('d',25),('c',24)]。我需要尽快完成。我的机器有很多 RAM,所以内存不是问题。

我有这个实现:

import numpy as np 
def getTopN(lst,N): 
 
    sOut = [] 
    cOut = [] 
 
    for l in lst: 
        for tpl in l: 
            s = tpl[0] 
            c = tpl[1] 
 
            try: 
                i = sOut.index(s) 
                cOut[i] += c 
            except: 
                sOut.append(s) 
                cOut.append(c) 
 
    sIndAsc = np.argsort(cOut).tolist() 
    sIndDes = sIndAsc[::-1] 
    cOutDes = [cOut[sir] for sir in sIndDes] 
    sOutDes = [sOut[sir] for sir in sIndDes] 
 
    return sOutDes[0:N],cOutDes[0:N] 

一定有更好的方法,但它会是什么?

请您参考如下方法:

使用collections.Counter :

import collections 
c = collections.Counter() 
for x in lst: 
    c.update(dict(x)) 
print(c.most_common(2)) 

输出:

[('d', 25), ('c', 24)] 

Counter 基本上是一个带有一些附加功能的字典,因此查找一个值并添加到它的当前计数非常快。 dict(x) 只会将元组列表转换为常规字典,将字符串映射到数字,然后 Counter 的 update 方法将添加这些计数(而不是像普通字典那样仅仅覆盖值)。

或者,使用 defaultdict 的更手动的方法:

c = collections.defaultdict(int) 
for x, y in (t for x in lst for t in x): 
    c[x] += y 
return [(k, c[k]) for k in sorted(c, key=c.get, reverse=True)][:2] 

正如 John 在评论中指出的那样,defaultdict 确实快得多:

In [2]: %timeit with_counter() 
10000 loops, best of 3: 17.3 µs per loop 
In [3]: %timeit with_dict() 
100000 loops, best of 3: 4.97 µs per loop