关于如何实际使用Python的itertools.groupby()函数,我还没有找到一个可以理解的解释。我想做的是:
取一个列表——在本例中是一个对象化lxml元素的子元素 根据某些标准将其分成几组 然后分别遍历这些组。
我已经查看了文档,但我很难将它们应用到简单的数字列表之外。
那么,如何使用itertools.groupby()呢?还有其他我应该使用的技巧吗?提供良好的“先决条件”阅读的指针也将受到赞赏。
关于如何实际使用Python的itertools.groupby()函数,我还没有找到一个可以理解的解释。我想做的是:
取一个列表——在本例中是一个对象化lxml元素的子元素 根据某些标准将其分成几组 然后分别遍历这些组。
我已经查看了文档,但我很难将它们应用到简单的数字列表之外。
那么,如何使用itertools.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'}
其他回答
排序和分组
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'}
警告:
语法列表(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功能,同时避免那些讨厌的(对于小数据)迭代器。
@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函数将不起作用!
这个基本实现帮助我理解了这个函数。希望它也能帮助到其他人:
arr = [(1, "A"), (1, "B"), (1, "C"), (2, "D"), (2, "E"), (3, "F")]
for k,g in groupby(arr, lambda x: x[0]):
print("--", k, "--")
for tup in g:
print(tup[1]) # tup[0] == k
-- 1 --
A
B
C
-- 2 --
D
E
-- 3 --
F
使用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']}