zl程序教程

您现在的位置是:首页 >  后端

当前栏目

《Python Cookbook(第3版)中文版》——1.15 根据字段将记录分组

Python 记录 根据 中文版 字段 分组 Cookbook 1.15
2023-09-11 14:17:38 时间

本节书摘来自异步社区《Python Cookbook(第3版)中文版》一书中的第1章,第1.15节,作者[美]David Beazley , Brian K.Jones,陈舸 译,更多章节内容可以访问云栖社区“异步社区”公众号查看。

1.15 根据字段将记录分组 1.15.1 问题

有一系列的字典或对象实例,我们想根据某个特定的字段(比如说日期)来分组迭代数据。

1.15.2 解决方案

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)来对序列排序,然后再使用itertools.groupby()。

from operator import itemgetter

from itertools import groupby

# Sort by the desired field first

rows.sort(key=itemgetter(date))

# Iterate in groups

for date, items in groupby(rows, key=itemgetter(date)):

 print(date)

 for i in items:

 print( , i)

这会产生如下的输出:

07/01/2012

 {date: 07/01/2012, address: 5412 N CLARK}

 {date: 07/01/2012, address: 4801 N BROADWAY}

07/02/2012

 {date: 07/02/2012, address: 5800 E 58TH}

 {date: 07/02/2012, address: 5645 N RAVENSWOOD}

 {date: 07/02/2012, address: 1060 W ADDISON}

07/03/2012

 {date: 07/03/2012, address: 2122 N CLARK}

07/04/2012

 {date: 07/04/2012, address: 5148 N CLARK}

 {date: 07/04/2012, address: 1039 W GRANVILLE}
1.15.3 讨论

函数groupby()通过扫描序列找出拥有相同值(或是由参数key指定的函数所返回的值)的序列项,并将它们分组。groupby()创建了一个迭代器,而在每次迭代时都会返回一个值(value)和一个子迭代器(sub_iterator),这个子迭代器可以产生所有在该分组内具有该值的项。

在这里重要的是首先要根据感兴趣的字段对数据进行排序。因为groupby()只能检查连续的项,不首先排序的话,将无法按所想的方式来对记录分组。

如果只是简单地根据日期将数据分组到一起,放进一个大的数据结构中以允许进行随机访问,那么利用defaultdict()构建一个一键多值字典(multidict,见1.6节)可能会更好。例如:

from collections import defaultdict

rows_by_date = defaultdict(list)

for row in rows:

 rows_by_date[row[date]].append(row)

这使得我们可以方便地访问每个日期的记录,如下所示:

 for r in rows_by_date[07/01/2012]:

... print(r)

{date: 07/01/2012, address: 5412 N CLARK}

{date: 07/01/2012, address: 4801 N BROADWAY}

 

对于后面这个例子,我们并不需要先对记录做排序。因此,如果不考虑内存方面的因素,这种方式会比先排序再用groupby()迭代要来的更快。


异步社区 异步社区(www.epubit.com)是人民邮电出版社旗下IT专业图书旗舰社区,也是国内领先的IT专业图书社区,致力于优质学习内容的出版和分享,实现了纸书电子书的同步上架,于2015年8月上线运营。公众号【异步图书】,每日赠送异步新书。