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

liste 发布于 2018-02-05 iteration 最后更新 2018-02-05 01:03 521 浏览

我一直无法找到如何实际使用Python的itertools.groupby()函数的可理解的解释。我想要做的是这样的:

  • 列出一个列表 - 在这种情况下,一个客体lxml元素的子元素
  • 根据一些标准将它分成组
  • 然后稍后再分别对这些组进行迭代。 我已经回顾了the documentationthe examples,但是我尝试将它们应用到一个简单的数字列表之外时遇到了麻烦。 那么,我该如何使用itertools.groupby()呢?还有另一种技术我应该使用?指出良好的“先决条件”阅读也将不胜感激。
已邀请:

wsed

赞同来自:

你能告诉我们你的代码吗? Python文档中的示例非常简单:

groups = []
uniquekeys = []
for k, g in groupby(data, keyfunc):
    groups.append(list(g))      # Store group iterator as a list
    uniquekeys.append(k)
所以在你的情况下,数据是一个节点列表,keyfunc是你的标准函数的逻辑去的地方,然后groupby()分组数据。 在调用groupby之前,必须谨慎地按照标准对数据进行排序,否则将无法工作。 groupby方法实际上只是迭代一个列表,每当关键改变它创建一个新的组。

liste

赞同来自:

正如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.
在这个例子中,things是元组的列表,其中每个元组中的第一个元素是第二个元素所属的组。 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.

bdicta

赞同来自:

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

[(c,len(list(cgen))) for c,cgen in groupby(some_string)]
会给你一个2元组列表,其中第一个元素是char,第二个元素是重复的数目。 编辑:请注意,这是从SQL GROUP BY语义分离itertools.groupby:itertools没有(一般不能)预先对迭代器进行排序,所以具有相同“键”的组合不会合并。

zvelit

赞同来自:

我试过你的例子,但是没有奏效。

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)]
正如你所看到的,有两个和两个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函数将不起作用

vomnis

赞同来自:

另一个例子:

for key, igroup in itertools.groupby(xrange(12), lambda x: x // 5):
    print key, list(igroup)
结果是
0 [0, 1, 2, 3, 4]
1 [5, 6, 7, 8, 9]
2 [10, 11]
请注意,igroup是一个迭代器(文档调用它的子迭代器)。 这对于分块生成器很有用:
def chunker(items, chunk_size):
    '''Group items in chunks of chunk_size'''
    for _key, group in itertools.groupby(enumerate(items), lambda x: x[0] // chunk_size):
        yield (g[1] for g in group)
with open('file.txt') as fobj:
    for chunk in chunker(fobj):
        process(chunk)
groupby的另一个例子 - 当键未被排序时。在以下示例中,xx中的项目按yy中的值分组。在这种情况下,首先输出一组零,然后是一组零,然后再一组零。
xx = range(10)
yy = [0, 0, 0, 1, 1, 1, 0, 0, 0, 0]
for group in itertools.groupby(iter(xx), lambda x: yy[x]):
    print group[0], list(group[1])
生产:
0 [0, 1, 2]
1 [3, 4, 5]
0 [6, 7, 8, 9]

ramet

赞同来自:

我想举另一个例子,groupby without sort不起作用。从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.
有两组车辆,而只有一组车辆

eea

赞同来自:

警告: 语法列表(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功能,同时避免那些烦人的(对于小数据)迭代器。

grem

赞同来自:

How do I use Python's itertools.groupby()?
您可以使用groupby将事物分组进行迭代。你给groupby一个可迭代的,和一个可选的函数/可调用,通过它来检查项目,当它们出来的迭代,它返回一个迭代器,给出了一个二元组的结果可调用的键和另一个可迭代的实际项目。从帮助:
groupby(iterable[, keyfunc]) -> create an iterator which returns
(key, sub-iterator) grouped by each value of key(value).
下面是一个groupby使用协程组来进行分组的示例,它使用一个可调用的键(在这种情况下,coroutine.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])]

ysunt

赞同来自:

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

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)

trerum

赞同来自:

Sorting and groupby
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'}

uin

赞同来自:

itertools.groupby是一个分组项目的工具。 从the docs起,我们会进一步收集它可能做的事情:

# [k for k, g in groupby('AAAABBBCCDAABBB')] --> A B C D A B # [list(g) for k, g in groupby('AAAABBBCCD')] --> AAAA BBB CC D
groupby对象在组是生成器的情况下生成键组对​​。 特征