python的itertools模块中的groupby

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))

 

发表于 2020年03月28日 02:06   修改于 2020年04月03日 09:57   评论:0   阅读:2019  



回到顶部

首页 | 关于我 | 关于本站 | 站内留言 | rss
python logo   django logo   tornado logo