如何使用itertools.groupby()?

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

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

我已经阅读了文档示例 ,可是尝试将它们应用到简单的数字列表以外却遇到了麻烦。 spa

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


#1楼

另外一个例子: code

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是一个迭代器(文档中称为子迭代器)。 xml

这对于分块生成器颇有用: 对象

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中的值分组。 在这种状况下,首先输出一组零,而后输出一组1,再输出一组零。 排序

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]

#2楼

@CaptSolo,我尝试了您的示例,但没有成功。 get

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函数将不起做用


#3楼

我想再举一个没有排序的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.

有两组带有车辆的车辆,而一个能够预期只有一组


#4楼

警告:

语法列表(groupby(...))不能按您指望的方式工做。 彷佛破坏了内部迭代器对象,所以使用

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

将产生:

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

代替list(groupby(...)),尝试[[k,list(g))for groupby(...)中的k,g,或者若是您常常使用该语法,

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

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


#5楼

如何使用Python的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])]
相关文章
相关标签/搜索