注意:我知道如何在显式的for循环中做到这一点,但我正在寻找一种更具可读性的解决方案。
如果可能的话,我想通过使用一些内置功能来解决这个问题。最佳案例场景类似于
result = [ *groupby logic* ]
假设以下列表:
import numpy as np
np.random.seed(42)
N = 10
my_tuples = list(zip(np.random.choice(list('ABC'), size=N),
np.random.choice(range(100), size=N)))
其中my_tuples
是
[('C', 74),
('A', 74),
('C', 87),
('C', 99),
('A', 23),
('A', 2),
('C', 21),
('B', 52),
('C', 1),
('C', 87)]
如何使用来自itertools的groupby
对标签A,B和C进行索引(每个元组的索引1处的整数值)?
如果我这样做:
from itertools import groupby
#..
[(k,*v) for k, v in dict(groupby(my_tuples, lambda x: x[0])).items()]
我发现这会导致错误的结果。
理想的结果应该是
{
'A': [74, 23, 2],
# ..
}
答案 0 :(得分:3)
最简单的解决方案可能根本不使用groupby
。
from collections import defaultdict
d = defaultdict(list)
for k, v in my_tuples:
d[k].append(v)
我不会使用groupby
的原因是因为groupby(iterable)
将iterable
中相邻的项目分组。因此,要将所有'C'
值组合在一起,首先必须对列表进行排序。除非您有某些理由使用groupby
,否则这是不必要的。
答案 1 :(得分:1)
您应该使用collections.defaultdict
作为O( n )解决方案,请参阅@PatrickHaugh's answer。
使用itertools.groupby
需要在分组前进行排序,从而产生O( n log n )复杂性:
from itertools import groupby
from operator import itemgetter
sorter = sorted(my_tuples, key=itemgetter(0))
grouper = groupby(sorter, key=itemgetter(0))
res = {k: list(map(itemgetter(1), v)) for k, v in grouper}
print(res)
{'A': [74, 23, 2],
'B': [52],
'C': [74, 87, 99, 21, 1, 87]}