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

取一个列表——在本例中是一个对象化lxml元素的子元素 根据某些标准将其分成几组 然后分别遍历这些组。

我已经查看了文档,但我很难将它们应用到简单的数字列表之外。

那么,如何使用itertools.groupby()呢?还有其他我应该使用的技巧吗?提供良好的“先决条件”阅读的指针也将受到赞赏。


当前回答

我遇到的一个有用的例子可能会有帮助:

from itertools import groupby

#user input

myinput = input()

#creating empty list to store output

myoutput = []

for k,g in groupby(myinput):

    myoutput.append((len(list(g)),int(k)))

print(*myoutput)

示例输入:14445221

样本输出:(1,1)(3,4)(1,5)(2,2)(1,1)

其他回答

我想再举一个例子,说明没有排序的groupby是行不通的。改编自James Sulak的例子

from itertools import groupby

things = [("vehicle", "bear"), ("animal", "duck"), ("animal", "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 vehicle.

A duck is a animal.
A cactus is a animal.

A speed boat is a vehicle.
A school bus is a vehicle.

有两组有车辆,而我们只能期待一组

@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函数将不起作用!

groupby的一个新技巧是在一行中运行长度编码:

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

会给你一个二元组列表,其中第一个元素是char,第二个元素是重复的次数。

编辑:注意这是itertools的区别。来自SQL GROUP BY语义的groupby: itertools不会(通常也不能)提前对迭代器排序,因此具有相同“key”的组不会合并。

使用itertools的关键是要认识到。Groupby是指只有在可迭代对象中是顺序的项才会被分组在一起。这就是排序工作的原因,因为基本上你在重新排列集合,以便所有满足callback(item)的项现在都按顺序出现在排序的集合中。

也就是说,您不需要对列表进行排序,只需要一个键-值对的集合,其中的值可以根据groupby生成的每个group iterable增长。例如,列表字典。

>>> things = [("vehicle", "bear"), ("animal", "duck"), ("animal", "cactus"), ("vehicle", "speed boat"), ("vehicle", "school bus")]
>>> coll = {}
>>> for k, g in itertools.groupby(things, lambda x: x[0]):
...     coll.setdefault(k, []).extend(i for _, i in g)
...
{'vehicle': ['bear', 'speed boat', 'school bus'], 'animal': ['duck', 'cactus']}

itertools。Groupby是一个对项目进行分组的工具。

从文档中,我们进一步收集了它可能做的事情:

# [k for k, g in groupby('AAAABBBCCDAABBB')]——> AB CDA B # [list(g) for k, g in groupby('AAAABBBCCD')]——> AAAABBBCC

Groupby对象产生键-组对,其中组是一个生成器。

特性

A.将连续的项目组合在一起 B.给定一个已排序的可迭代对象,对一个项目的所有出现进行分组 C.指定如何使用键功能*对项目进行分组

比较

# Define a printer for comparing outputs
>>> def print_groupby(iterable, keyfunc=None):
...    for k, g in it.groupby(iterable, keyfunc):
...        print("key: '{}'--> group: {}".format(k, list(g)))
# Feature A: group consecutive occurrences
>>> print_groupby("BCAACACAADBBB")
key: 'B'--> group: ['B']
key: 'C'--> group: ['C']
key: 'A'--> group: ['A', 'A']
key: 'C'--> group: ['C']
key: 'A'--> group: ['A']
key: 'C'--> group: ['C']
key: 'A'--> group: ['A', 'A']
key: 'D'--> group: ['D']
key: 'B'--> group: ['B', 'B', 'B']

# Feature B: group all occurrences
>>> print_groupby(sorted("BCAACACAADBBB"))
key: 'A'--> group: ['A', 'A', 'A', 'A', 'A']
key: 'B'--> group: ['B', 'B', 'B', 'B']
key: 'C'--> group: ['C', 'C', 'C']
key: 'D'--> group: ['D']

# Feature C: group by a key function
>>> # islower = lambda s: s.islower()                      # equivalent
>>> def islower(s):
...     """Return True if a string is lowercase, else False."""   
...     return s.islower()
>>> print_groupby(sorted("bCAaCacAADBbB"), keyfunc=islower)
key: 'False'--> group: ['A', 'A', 'A', 'B', 'B', 'C', 'C', 'D']
key: 'True'--> group: ['a', 'a', 'b', 'b', 'c']

Uses

Anagrams (see notebook) Binning Group odd and even numbers Group a list by values Remove duplicate elements Find indices of repeated elements in an array Split an array into n-sized chunks Find corresponding elements between two lists Compression algorithm (see notebook)/Run Length Encoding Grouping letters by length, key function (see notebook) Consecutive values over a threshold (see notebook) Find ranges of numbers in a list or continuous items (see docs) Find all related longest sequences Take consecutive sequences that meet a condition (see related post)

注意:后面的几个例子来自Víctor Terrón的PyCon (talk)(西班牙语),“Kung Fu at Dawn with Itertools”。请参见用C语言编写的groupby源代码。

*一个函数,其中所有项都被传递和比较,影响结果。其他具有key函数的对象包括sorted(), max()和min()。


响应

# OP: Yes, you can use `groupby`, e.g. 
[do_something(list(g)) for _, g in groupby(lxml_elements, criteria_func)]