如何使用Python的itertools.groupby()?

时间:2020-03-05 18:37:25  来源:igfitidea点击:

我还没有找到关于如何实际使用Python的itertools.groupby()函数的可理解的解释。我想做的是这样的:

列出一个列表-在这种情况下,是一个对象化的lxml元素的子元素,并根据一些标准将其分为几组,然后分别遍历这些组中的每一个。

我已经阅读了文档和示例,但是尝试将其应用于简单的数字列表之外却遇到了麻烦。

那么,如何使用itertools.groupby()?我应该使用另一种技术吗?指向良好"前提"阅读的指针也将受到赞赏。

解决方案:

我们能告诉我们代码吗?

Python文档上的示例非常简单:

groups = []
uniquekeys = []
for k, g in groupby(data, keyfunc):
    groups.append(list(g))      # Store group iterator as a list
    uniquekeys.append(k)

因此,在情况下,data是节点的列表,keyfunc是条件函数的逻辑所在的位置,然后groupby()对数据进行分组。

在调用groupby之前,我们必须小心按照条件对数据进行排序,否则它将无法正常工作。实际上," groupby"方法只是遍历一个列表,并且每当键更改时,它就会创建一个新的组。

正如Sebastjan所说,我们首先必须对数据进行排序。这个很重要。

我没有得到的部分是在示例构造中

groups = []
uniquekeys = []
for k, g in groupby(data, keyfunc):
   groups.append(list(g))    # Store group iterator as a list
   uniquekeys.append(k)

" k"是当前的分组键,而" g"是一个迭代器,我们可以使用该迭代器在该分组键定义的组上进行迭代。换句话说,groupby迭代器本身返回迭代器。

这是一个使用更清晰的变量名的示例:

from itertools import groupby

things = [("animal", "bear"), ("animal", "duck"), ("plant", "cactus"), ("vehicle", "speed boat"), ("vehicle", "school bus")]

for key, group in groupby(things, lambda x: x[0]):
    for thing in group:
        print "A %s is a %s." % (thing[1], key)
    print " "

这将为我们提供输出:

A bear is a animal.

  A duck is a animal.
  
  A cactus is a plant.
  
  A speed boat is a vehicle.

  A school bus is a vehicle.

在此示例中,"事物"是元组的列表,其中每个元组中的第一项是第二项所属的组。

groupby()函数有两个参数:(1)要分组的数据和(2)与数据分组的函数。

在这里," lambda x:x [0]"告诉" groupby()"将每个元组中的第一项用作分组键。

在上面的" for"语句中," groupby"为每个唯一键返回三对(键,组迭代器)对。我们可以使用返回的迭代器来迭代该组中的每个单个项目。

这是一个使用列表推导的具有相同数据的稍有不同的示例:

for key, group in groupby(things, lambda x: x[0]):
    listOfThings = " and ".join([thing[1] for thing in group])
    print key + "s:  " + listOfThings + "."

这将为我们提供输出:

animals: bear and duck.

  plants: cactus.

  vehicles: speed boat and school bus.

使用groupby的一个妙招是在一行中运行长度编码:

[(c,len(list(cgen))) for c,cgen in groupby(some_string)]

将为我们提供2元组的列表,其中第一个元素是char,第二个是重复数。

编辑:请注意,这是将" itertools.groupby"与SQL" GROUP BY"语义分开的内容:itertools不会(通常不能)事先对迭代器进行排序,因此具有相同"键"的组不会t合并。

@CaptSolo,我尝试了示例,但是没有用。

from itertools import groupby 
[(c,len(list(cs))) for c,cs in groupby('Pedro Manoel')]

输出:

[('P', 1), ('e', 1), ('d', 1), ('r', 1), ('o', 1), (' ', 1), ('M', 1), ('a', 1), ('n', 1), ('o', 1), ('e', 1), ('l', 1)]

如我们所见,有两个o和两个e,但是它们分成不同的组。从那时起,我意识到我们需要对传递给groupby函数的列表进行排序。因此,正确的用法是:

name = list('Pedro Manoel')
name.sort()
[(c,len(list(cs))) for c,cs in groupby(name)]

输出:

[(' ', 1), ('M', 1), ('P', 1), ('a', 1), ('d', 1), ('e', 2), ('l', 1), ('n', 1), ('o', 2), ('r', 1)]

请记住,如果列表未排序,groupby函数将不起作用!