如何使用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])]
相關文章
相關標籤/搜索