关于groupby()的正确用法:Python 3

时间:2014-01-03 07:54:57

标签: python

我没有任何问题弄清楚如何在itertools中应用这些函数,直到我到达groupby(iterable, key=None),我立即阅读了这个例子并且它没有完全点击我导致我在谷歌上研究它。我最终找到了一个example;然而,它并没有真正分解为一切都有意义。据我所知,groupby()子迭代一个有序的迭代?

我的问题:任何人都可以提供更新的Python 3,解释{Barner-Style“中的groupby()函数吗?

1 个答案:

答案 0 :(得分:7)

Groupby根据某些用户指定的特征将连续项组合在一起。生成的迭代器中的每个元素都是一个元组,其中第一个元素(在我的示例中为group)是“key”,它是该组的标签。第二个元素(在我的示例中为items)是该组中项目的迭代器。

在最简单的情况下,特征就是身份,这意味着它将同一事物的“运行”组合在一起:

>>> for group, items in itertools.groupby('aabbbccdddee'):
...     print group, list(items)
a [u'a', u'a']
b [u'b', u'b', u'b']
c [u'c', u'c']
d [u'd', u'd', u'd']
e [u'e', u'e']

但是,您也可以将一个键函数传递给组,而不仅仅是对相同元素的运行,而是以您指定的某种方式运行“相同”的元素:

>>> for group, items in itertools.groupby('aaAaAAbBbcCdDdDeE', lambda x: x.lower()):
...     print group, list(items)
a [u'a', u'a', u'A', u'a', u'A', u'A']
b [u'b', u'B', u'b']
c [u'c', u'C']
d [u'd', u'D', u'd', u'D']
e [u'e', u'E']

这里我使用了一个返回其输入的小写形式的键函数。这意味着如果项目的小写形式相同,则会对项目进行分组。如果没有关键功能,只有在项目完全相同的情况下才会对项目进行分组:

>>> for group, items in itertools.groupby('aaAaAAbBbcCdDdDeE'):
...     print group, list(items)
a [u'a', u'a']
A [u'A']
a [u'a']
A [u'A', u'A']
b [u'b']
B [u'B']
b [u'b']
c [u'c']
C [u'C']
d [u'd']
D [u'D']
d [u'd']
D [u'D']
e [u'e']
E [u'E']

这里我们有很多单元素组,因为即使案例中的变化也算作组中的差异。

最后一个示例还显示了一个重要的问题:groupby仅将属于同一组的连续元素组合在一起。因此,即使我的数据中有很多“a”,但它们并非全部组合在一起,因为它们不是连续的。

在这些示例中,我只使用list向您展示了每个组中的所有内容。实际上,每个组都是一个迭代器,因此只能根据需要生成项目。这里也存在潜在的问题,因为如果你遍历那个群体,一个群体的内容会“消失”:

>>> grouped = itertools.groupby('aabbbccdddee')
>>> group, items = next(grouped)
>>> print group, items   # the "_grouper" object is an iterator of items in group "a"
a <itertools._grouper object at 0x0000000002648DA0>
>>> next(grouped)   # we move to the next group
(u'b', <itertools._grouper object at 0x0000000002648630>)
>>> print list(items)   # oops, items vanished!
[]

发生了什么事情,因为我们做了next(grouped),我们移过了“a”组,当我们这样做时,石斑鱼“忘记了”那个组中的内容。这通常不是问题,因为通常你会发现你正确使用每个组。但是,如果您想稍后存储一个组,则需要使用list列出项目列表,而不是仅存储_grouper个对象。

通过使用键功能,您可以对各种事物进行分组,但基本思路是相同的:groupby“chunks”项目序列与您指定的方式“相同”。