Python 通过某个字段将记录分组
2020-05-29 本文已影响0人
大梦三千秋
通过某个字段将记录分组
问题
假设有一个字典或者实例的序列,想根据某个特定的字段进行分组迭代访问?
解决方法
Python 提供的 itertools
模块中有个 groupby()
函数,能够实现对数据进行分组操作。模拟字典数据如下:
rows = [
{'address': '5412 N CLARK', 'date': '07/01/2012'},
{'address': '5148 N CLARK', 'date': '07/04/2012'},
{'address': '5800 E 58TH', 'date': '07/02/2012'},
{'address': '2122 N CLARK', 'date': '07/03/2012'},
{'address': '5645 N RAVENSWOOD', 'date': '07/02/2012'},
{'address': '1060 W ADDISON', 'date': '07/02/2012'},
{'address': '4801 N BROADWAY', 'date': '07/01/2012'},
{'address': '1039 W GRANVILLE', 'date': '07/04/2012'},
]
假设,要以 date
进行分组,将分块的数据进行迭代。这里首先要对指定的字段(这里为 date
) 进行排序 ,然后调用 groupby()
函数。
from operator import itemgetter
from itertools import groupby
# 首先以 "date" 进行排序
rows.sort(key=itemgetter('date'))
# 遍历分组后的数据块
for date, items in groupby(rows, key=itemgetter('date')):
print(date)
for item in items:
print(' ', item)
下面是允许后的结果:
07/01/2012
{'address': '5412 N CLARK', 'date': '07/01/2012'}
{'address': '4801 N BROADWAY', 'date': '07/01/2012'}
07/02/2012
{'address': '5800 E 58TH', 'date': '07/02/2012'}
{'address': '5645 N RAVENSWOOD', 'date': '07/02/2012'}
{'address': '1060 W ADDISON', 'date': '07/02/2012'}
07/03/2012
{'address': '2122 N CLARK', 'date': '07/03/2012'}
07/04/2012
{'address': '5148 N CLARK', 'date': '07/04/2012'}
{'address': '1039 W GRANVILLE', 'date': '07/04/2012'}
代码解析
groupby()
函数运行的机制是先扫描整个序列,同时查找连续相同值的元素序列。每次迭代返回的结果,包含一个值和一个迭代器对象,这个迭代器对象可以生产元素值全部等于上面那个值的组中所有对象。
这里需要注意的是,要预先对指定的字段进行排序。因为 groupby()
仅仅检查连续的元素,如果没有事先进行排序,将达不到效果。
如果仅仅是根据 date
字段将数据分组到一个大的数据结构中,而且可以随机访问。这里可以使用另外一种方法,使用 defaultdict()
构建多值字典,示例如下:
from collections import defaultdict
rows_by_date = defaultdict(list)
for row in rows:
rows_by_date[rows['date']].append(row)
这个时候,就可以根据指定的日期访问对应的记录:
for row in rows_by_date['07/01/2012']:
print(row)
# result:
# {'date': '07/01/2012', 'address': '5412 N CLARK'}
# {'date': '07/01/2012', 'address': '4801 N BROADWAY'}
这部分代码无须对原序列数据进行排序。这种情况下,这种方式会比先排序后使用 groupby()
函数分组再进行迭代会快。
以上为本篇的主要内容。