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

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

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

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


当前回答

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

其他回答

排序和分组

from itertools import groupby

val = [{'name': 'satyajit', 'address': 'btm', 'pin': 560076}, 
       {'name': 'Mukul', 'address': 'Silk board', 'pin': 560078},
       {'name': 'Preetam', 'address': 'btm', 'pin': 560076}]


for pin, list_data in groupby(sorted(val, key=lambda k: k['pin']),lambda x: x['pin']):
...     print pin
...     for rec in list_data:
...             print rec
... 
o/p:

560076
{'name': 'satyajit', 'pin': 560076, 'address': 'btm'}
{'name': 'Preetam', 'pin': 560076, 'address': 'btm'}
560078
{'name': 'Mukul', 'pin': 560078, 'address': 'Silk board'}

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

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)

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

您可以使用groupby来对迭代进行分组。你给groupby一个可迭代对象,和一个可选的键函数/可调用对象,用来检查从可迭代对象中取出的项,它返回一个迭代器,给出一个由可调用键的结果和另一个可迭代对象中的实际项组成的二元组。来自帮助:

groupby(iterable[, keyfunc]) -> create an iterator which returns
(key, sub-iterator) grouped by each value of key(value).

下面是groupby使用协程按计数分组的例子,它使用一个键可调用对象(在本例中是corroutine .send)来输出迭代次数的计数和元素的分组子迭代器:

import itertools


def grouper(iterable, n):
    def coroutine(n):
        yield # queue up coroutine
        for i in itertools.count():
            for j in range(n):
                yield i
    groups = coroutine(n)
    next(groups) # queue up coroutine

    for c, objs in itertools.groupby(iterable, groups.send):
        yield c, list(objs)
    # or instead of materializing a list of objs, just:
    # return itertools.groupby(iterable, groups.send)

list(grouper(range(10), 3))

打印

[(0, [0, 1, 2]), (1, [3, 4, 5]), (2, [6, 7, 8]), (3, [9])]

使用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']}

警告:

语法列表(groupby(…))不会按您想要的方式工作。它似乎破坏了内部迭代器对象,所以使用

for x in list(groupby(range(10))):
    print(list(x[1]))

会产生:

[]
[]
[]
[]
[]
[]
[]
[]
[]
[9]

而不是list(groupby(…)),尝试[(k, list(g)) for k,g in groupby(…)],或者如果你经常使用这种语法,

def groupbylist(*args, **kwargs):
    return [(k, list(g)) for k, g in groupby(*args, **kwargs)]

并且可以访问groupby功能,同时避免那些讨厌的(对于小数据)迭代器。