列表推导可以等价于SQL中的'count(*)...group by...'吗?

5 投票
5 回答
6818 浏览
提问于 2025-04-15 18:33

我觉得列表推导式可能能帮我实现这个,但我不太确定:在Python(2.6)中,有没有什么优雅的方法可以从一个列表中选择唯一的对象并提供计数?

(我在我的对象定义中定义了一个__eq__方法来判断对象的唯一性。)

在关系数据库的世界里,类似这样的操作:

CREATE TABLE x(n NUMBER(1));
INSERT INTO x VALUES(1);
INSERT INTO x VALUES(1);
INSERT INTO x VALUES(1);
INSERT INTO x VALUES(2);

SELECT COUNT(*), n FROM x
GROUP BY n;

这样会得到:

COUNT(*) n
==========
3        1
1        2

那么,这就是我在Python中的等效列表:

[1,1,1,2]

我想要的输出和上面SQL SELECT的结果是一样的。

编辑:我这里给出的例子是简化过的,实际上我在处理的是用户定义的对象实例列表:为了完整起见,我把实现这个功能所需的额外代码也包括在内:

import hashlib

def __hash__(self):
    md5=hashlib.md5()
    [md5.update(i) for i in self.my_list_of_stuff]
    return int(md5.hexdigest(),16)

需要__hash__方法才能让set转换正常工作(我选择了在2.6中有效的列表推导式方法【尽管我了解到这会有一些效率问题(见评论)——但我的数据集足够小,所以这不是问题】)。上面的my_list_of_stuff是我对象定义中的一个字符串列表。

5 个回答

6

这件事用列表推导式来做不太容易。

from collections import defaultdict
def group_by( someList ):
    counts = defaultdict(int)
    for value in someList:
        counts[value.aKey] += 1
    return counts

这个方法在Python中很常见,但它不是列表推导式。

11
>>> from collections import Counter
>>> Counter([1,1,1,2])
Counter({1: 3, 2: 1})

Counter 这个东西只在 Python 3.1 版本中可以用,它是从 dict(字典)这个数据结构派生出来的。

12

Lennart Regebro 提供了一个很简洁的代码行,可以实现你想要的功能:

>>> values = [1,1,1,2]
>>> print [(x,values.count(x)) for x in set(values)]
[(1, 3), (2, 1)]

正如 S.Lott 提到的,使用 defaultdict 也能做到同样的事情。

撰写回答