itertools提供了很多迭代器相关的操作,而且这些操作是内置于解释器的,即效率非常高。
该模块提供了很多函数,但这里专门讨论groupby。该函数可以很方便的用来对数据进行分组,有点像mysql里的group by,但是又不太一样,一方面它只归并相邻一样的元素,另一方面它只是返回迭代器,同时它还保持原来的次序。
比如,你要将一个list进行mysql那样的分组,最终得到一个dict的list结构:
s = [1,1,2,2,3,2]
{i:list(j) for i,j in groupby(sorted(s))} ==> {1: [1, 1], 2: [2, 2, 2], 3: [3]}
比如,要将一系列的单词按首字母进行归类:
from operator import itemgetter
s = ['name', 'age', 'apple', 'nerd', 'banana']
[(i, list(j)) for i,j in groupby(sorted(s, key=itemgetter(0)), itemgetter(0))]
==> [('a', ['age', 'apple']), ('b', ['banana']), ('n', ['name', 'nerd'])]
比如,要取一个字符串中连续字符的首字符:
for i in map(itemgetter(0), groupby('AABBAACCDEEBB')):
print(i) ==> 'ABACDEB'
上面这个例子需要注意:我们使用map,而不使用list,是因为map返回的是迭代器,很多时候我们只是需要遍历中间结果,但并不需要全部存储它们。这个根据实际情况选择。
上面的例子如果变得复杂一些,不区分大小写的连续字符,即a和A也认为是连续:
for i in map(next, map(itemgetter(1), groupby('AABBaACcDEEBB', str.lower))):
print(i) ==> ABaCDEB
如何判断一个列表里的所有元素都相等,如果用for循环当然没问题,官方文档里给出一种更简洁的实现:
def all_equal(iterable):
"Returns True if all the elements are equal to each other"
g = groupby(iterable)
return next(g, True) and not next(g, False)
itertools里有些函数乍一看好像没啥用,但是说不定什么时候就能用上,比如:有一个字符串,可能以|或^或&作分隔,获取分隔符前半部分的内容,因为分隔符有多种,所以split搞不定了,如果用正则匹配又有点杀鸡用牛刀,那么可以这样写:
#获取分隔符前的部分
''.join(itertools.takewhile(lambda x:x not in '|^&', s))
#获取分隔符后的部分,包括分隔符
''.join(itertools.dropwhile(lambda x:x not in '|^&', s))