如何分组元组列表?

时间:2018-05-31 12:30:54

标签: python sorting dictionary grouping itertools

注意:我知道如何在显式的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],
  # ..
}

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]}