首页 » 编程开发 » Python » 正文

Python标准库13 循环器 itertools:itertools.groupby使用方法实例

标准库中的itertools包提供了更加灵活的生成循环器的工具。这些工具的输入大都是已有的循环器。另一方面,这些工具完全可以自行使用Python实现,该包只是提供了一种比较标准、高效的实现方式。这也符合Python“只有且最好只有解决方案”的理念。

其中itertools.groupby(iterable[, key]) 这个函数功能类似于SQL的分组。使用groupby前,首先需要使用相同的keyfunc对iterable进行排序,比如调用内建的sorted函数。然后,groupby返回迭代器,每次迭代的元素是元组(key值, iterable中具有相同key值的元素的集合的子迭代器)。

下面举例:

from itertools import *

def height_class(h):
if h > 180:
return “tall”
elif h < 160:
return “short”
else:
return “middle”

friends = [191, 158, 159,159, 165, 170, 177, 181, 182, 190]

friends = sorted(friends, key = height_class)
print friends
for m, n in groupby(friends, key = height_class):
print(m)
print(list(n))

运行输出结果为:

[165, 170, 177, 158, 159, 159, 191, 181, 182, 190]
middle
[165, 170, 177]
short
[158, 159, 159]
tall
[191, 181, 182, 190]

将上面代码保存为.py文件,即可运行测试。itertools.groupby方法在调用之前,必须先进行排序操作,“friends = sorted(friends, key = height_class)”将数组内的数据进行了排序,大家可以从打印信息里面看到,随后调用itertools.groupby里面进行了生成子迭代器的过程,此方法按照函数height_class定义的分组方法,将数据friends 里面的数据进行遍历并分组,参数m即为分组后的key,而list(n)就代表每个子迭代器,通过打印,一目了然,就不多说了。
不知道大家注意到没,我在friends数组里面故意将“159”这个数值重复了两遍,从最后打印的结果来看,itertools.groupby调用之后并没有任何变化,两个159都被分配到short组了。其实,itertools.groupby方法也是可以用来去重的,具体的方法,请先看下面的例子:

from itertools import *

ids = [1,4,3,3,4,2,3,4,5,6,1]
ids.sort()
it = groupby(ids)
for k, g in it:
print k

运行输出结果为:

1
2
3
4
5
6

可以看到,ids 这个数组本来很多的重复值,经过区区两行代码的处理,成功去重了。大家可以注意到,在这个例子中,groupby方法调用的时候并没有key这个参数,那么就是说,在不定义分组也就是key参数缺省的情况下,它会按照数组里面的单个值进行分组排序,如果有重复的值,那么它们将会被分配到一个组——即一个子迭代器里面。这个例子中for循环内,如果我们跟上面第一个例子一样打印“list(g)”,就可以看到子迭代器里面的值了,大家可以自己验证一下。
最后再说一遍,itertools.groupby方法在调用之前,一定要先排序。总的看起来,跟sql语句里面的group by方法真的好相似。

发表评论