1.15 通过æŸ�ä¸ªå—æ®µå°†è®°å½•分组¶
问题¶
ä½ æœ‰ä¸€ä¸ªå—典或者实例的åº�列,然å�Žä½ æƒ³æ ¹æ�®æŸ�ä¸ªç‰¹å®šçš„å—æ®µæ¯”如 date æ�¥åˆ†ç»„è¿ä»£è®¿é—®ã€‚
解决方案¶
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 )排åº�,
然�调用 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'}
讨论¶
groupby() 函数扫æ��整个åº�列并且查找连ç»ç›¸å�Œå€¼ï¼ˆæˆ–è€…æ ¹æ�®æŒ‡å®š key 函数返回值相å�Œï¼‰çš„å…ƒç´ åº�列。
在æ¯�次è¿ä»£çš„æ—¶å€™ï¼Œå®ƒä¼šè¿”回一个值和一个è¿ä»£å™¨å¯¹è±¡ï¼Œ
这个è¿ä»£å™¨å¯¹è±¡å�¯ä»¥ç”Ÿæˆ�å…ƒç´ å€¼å…¨éƒ¨ç‰äºŽä¸Šé�¢é‚£ä¸ªå€¼çš„ç»„ä¸æ‰€æœ‰å¯¹è±¡ã€‚
一个é�žå¸¸é‡�è¦�的准备æ¥éª¤æ˜¯è¦�æ ¹æ�®æŒ‡å®šçš„å—æ®µå°†æ•°æ�®æŽ’åº�。
å› ä¸º groupby() 仅仅检查连ç»çš„å…ƒç´ ï¼Œå¦‚æžœäº‹å…ˆå¹¶æ²¡æœ‰æŽ’åº�完æˆ�çš„è¯�,分组函数将得ä¸�到想è¦�的结果。
å¦‚æžœä½ ä»…ä»…å�ªæ˜¯æƒ³æ ¹æ�® date å—æ®µå°†æ•°æ�®åˆ†ç»„到一个大的数æ�®ç»“æž„ä¸åŽ»ï¼Œå¹¶ä¸”å…�许éš�机访问,
é‚£ä¹ˆä½ æœ€å¥½ä½¿ç”¨ defaultdict() æ�¥æž„建一个多值å—典,关于多值å—典已ç»�在 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() 函数è¿ä»£çš„æ–¹å¼�è¿�行得快一些。