- Python算法详解
- 张玲玲
- 810字
- 2020-06-27 17:50:51
2.3.9 根据记录进行分组
在Python程序中,可以将字典或对象实例中的信息根据某个特定的字段(比如日期)分组迭代数据。在Python的itertools模块中提供了内置函数groupby(),能够方便地对数据进行分组处理。使用函数groupby()的语法格式如下所示:
groupby(iterable [,key]):
函数groupby()能够创建一个迭代器,对iterable生成的连续项进行分组,在分组过程中会查找重复项。如果iterable在多次连续迭代中生成同一项,则会定义一个组。如果将函数groupby()应用到一个分类列表中,那么分组将定义该列表中的所有唯一项。key(如果已提供)是一个函数,被应用于每一项,如果此函数存在返回值,该值将用于后续项而不是该项本身的比较,此函数返回的迭代器生成元素(key, group),其中key是分组的键值,group是迭代器,生成组成该组的所有项。
下面的实例文件fen.py演示了使用函数groupby()对数据进行分组的过程。
源码路径:daima\第2章\fen.py
from itertools import groupby from operator import itemgetter things = [('2012-05-21', 11), ('2012-05-21', 3), ('2012-05-22', 10), ('2012-05-22', 4), ('2012-05-22', 22),('2012-05-23', 33)] for key, items in groupby(things, itemgetter(0)): print(key) for subitem in items: print(subitem) print('-' * 20)
执行后会输出:
2012-05-21 2012-05-22 2012-05-23 ('2012-05-23', 33)
再看下面的实例文件fenzu.py,演示了使用函数groupby()分组复杂数据的过程。
源码路径:daima\第2章\fenzu.py
①rows = [ {'address': '5412 N CLARK', 'data': '07/01/2018'}, {'address': '5232 N CLARK', 'data': '07/04/2018'}, {'address': '5542 E 58ARK', 'data': '07/02/2018'}, {'address': '5152 N CLARK', 'data': '07/03/2018'}, {'address': '7412 N CLARK', 'data': '07/02/2018'}, {'address': '6789 w CLARK', 'data': '07/03/2018'}, {'address': '9008 N CLARK', 'data': '07/01/2018'}, {'address': '2227 W CLARK', 'data': '07/04/2018'} ] ②from operator import itemgetter from itertools import groupby rows.sort(key=itemgetter('data')) for data, items in groupby(rows, key=itemgetter('data')): print(data) for i in items: ③ print(' ', i) ④from collections import defaultdict rows_by_date = defaultdict(list) for row in rows: ⑤ rows_by_date[row['data']].append(row) ⑥for r in rows_by_date['07/04/2018']: print(r)
在①中创建包含时间和地址的一系列字典数据。
在②~③中根据日期以分组的方式迭代数据,首先以目标字段date对序列进行排序,然后使用itertools.groupby()函数进行分组。这里的重点是,首先要根据感兴趣的字段对数据进行排序,因为函数groupby()只能检查连续的项,如果不首先排序的话,将无法按照预想的方式对记录进行分组。
如果只是想简单地根据日期将数据分组到一起,并放进一个大的数据结构以允许进行随机访问,那么建议像④~⑤那样使用函数defaultdict()构建一个一键多值字典。
在⑥中访问每个日期的记录。
执行上述代码后会输出:
07/01/2018 {'address': '5412 N CLARK', 'data': '07/01/2018'} {'address': '9008 N CLARK', 'data': '07/01/2018'} 07/02/2018 {'address': '5542 E 58ARK', 'data': '07/02/2018'} {'address': '7412 N CLARK', 'data': '07/02/2018'} 07/03/2018 {'address': '5152 N CLARK', 'data': '07/03/2018'} {'address': '6789 w CLARK', 'data': '07/03/2018'} 07/04/2018 {'address': '5232 N CLARK', 'data': '07/04/2018'} {'address': '2227 W CLARK', 'data': '07/04/2018'} {'address': '5232 N CLARK', 'data': '07/04/2018'} {'address': '2227 W CLARK', 'data': '07/04/2018'}