如何对元组列表进行分组?

Posted

技术标签:

【中文标题】如何对元组列表进行分组?【英文标题】:How to group list of tuples? 【发布时间】:2018-05-31 12:30:54 【问题描述】:

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

【问题讨论】:

在下面你说你想要一个单行,但在这里你说你想要更多可读性。更少的行数并不一定意味着可读性更高,事实上,如果你尝试做太多事情,通常意味着可读性会大大降低。 作为提供itertools 答案的人,我完全同意@glibdud。可读性通常并不意味着单行化。 collections.defaultdict 的复杂度也较低。 @glibdud 好吧,我完全同意这里。但我保证我离开了我尝试编写“酷代码”的阶段:D 【参考方案1】:

最简单的解决方案可能是根本不使用groupby

from collections import defaultdict

d = defaultdict(list)

for k, v in my_tuples:
    d[k].append(v)

我不使用groupby 的原因是groupby(iterable)iterable 中相邻的项目分组。因此,要将所有 'C' 值放在一起,您首先必须对列表进行排序。除非你有理由使用groupby,否则没有必要。

【讨论】:

我实际上是希望找到一个“简单”的单行代码来保持代码更干净。我更喜欢我写result = [ *groupby* ]的解决方案。 @StefanFalk 我建议您提到您希望结果在您的原始问题中成为单行,以便下次获得更好的答案。 这就是我专门询问groupby 的原因,但你是对的,我在寻找什么并不是很明显。【参考方案2】:

对于 O(n) 解决方案,您应该使用 collections.defaultdict,请参阅 @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]

【讨论】:

啊,现在我明白了.. +1 提醒我们时间复杂性。 不错。但是,这是 3 行。 不,我更喜欢你的 3 班轮。 OP 不喜欢帕特里克的解决方案,因为它不是一个单一的班轮并接受这一点。 @Attersson,是的,我同意你的观点,defaultdict 更好(我赞成)。但出于教育目的,有必要了解itertools.groupby 的工作原理。 @Attersson 你可以去掉 sortergrouper (不是说这看起来不错,但没有必要声明它们)。 jpp 也得到了它:我接受了他的回答,因为我在询问 groupby,我认为人们最终可能会在这里寻找 groupby 的例子。

以上是关于如何对元组列表进行分组?的主要内容,如果未能解决你的问题,请参考以下文章

如何按两个元素对元组列表进行排序?

如何在 Python 中对元组列表列表进行平面映射? [复制]

如何根据另一个列表对元组列表进行排序

如何在 Python 中对元组列表进行 enumerate()?

如何根据另一个列表中元组元素的顺序对元组列表进行排序?

按元组的第二个元素对元组列表进行排序,无需高阶函数或递归