Answers:
重要说明:您必须先对数据进行排序。
我没有得到的部分是在示例构造中
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 " "
这将为您提供输出:
熊是动物。
鸭子是动物。仙人掌是植物。
快艇是车辆。
校车是车辆。
在此示例中,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 + "."
这将为您提供输出:
动物:熊和鸭。
植物:仙人掌。
车辆:快艇和校车。
groupby(sorted(my_collection, key=lambda x: x[0]), lambda x: x[0]))
假设下my_collection = [("animal", "bear"), ("plant", "cactus"), ("animal", "duck")]
,你的希望集团animal or plant
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
方法实际上只是遍历列表,并且每当键更改时,它都会创建一个新组。
keyfunc
就像“是的,我确切地知道那是什么,因为该文档非常简单。”?难以置信!
itertools.groupby
是用于分组项目的工具。
从文档中,我们进一步了解了它的作用:
# [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
对象产生密钥组对,其中组是生成器。
特征
比较
# 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
>>> # keyfunc = lambda s: s.islower() # equivalent
>>> def keyfunc(s):
... """Return a True if a string is lowercase, else False."""
... return s.islower()
>>> print_groupby(sorted("bCAaCacAADBbB"), keyfunc)
key: 'False'--> group: ['A', 'A', 'A', 'B', 'B', 'C', 'C', 'D']
key: 'True'--> group: ['a', 'a', 'b', 'b', 'c']
用途
注意:后面的几个示例来自VíctorTerrón的PyCon (谈话) (西班牙语),“黎明时的功夫与Itertools”。另请参见用C编写的groupby
源代码。
*传递和比较所有项目,影响结果的功能。按键功能的对象包括 sorted()
,max()
和min()
。
响应
# OP: Yes, you can use `groupby`, e.g.
[do_something(list(g)) for _, g in groupby(lxml_elements, criteria_func)]
[''.join(g) for k, g in groupby('AAAABBBCCD')] --> AAAA BBB CC D
。
list()
,tuple()
)或消耗在一个循环/理解显示的内容。这些冗余可能被作者排除在外以节省空间。
另一个例子:
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]
警告:
语法列表(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功能,同时避免了那些讨厌的(对于小数据)迭代器。
我想再举一个没有排序的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.
有两组带有车辆的车辆,而一个可以预期只有一组
@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函数将无法工作!
排序和分组
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'}
如何使用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])]
您可以编写自己的groupby函数:
def groupby(data):
kv = {}
for k,v in data:
if k not in kv:
kv[k]=[v]
else:
kv[k].append(v)
return kv
Run on ipython:
In [10]: data = [('a', 1), ('b',2),('a',2)]
In [11]: groupby(data)
Out[11]: {'a': [1, 2], 'b': [2]}