1.15 通過某個字段將記錄分組

2018-02-24 15:26 更新

問題

你有一個字典或者實(shí)例的序列,然后你想根據(jù)某個特定的字段比如date來分組迭代訪問。

解決方案

itertools.groupby() 函數(shù)對于這樣的數(shù)據(jù)分組操作非常實(shí)用。為了演示,假設(shè)你已經(jīng)有了下列的字典列表:

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'},
]

現(xiàn)在假設(shè)你想在按date分組后的數(shù)據(jù)塊上進(jìn)行迭代。為了這樣做,你首先需要按照指定的字段(這里就是date)排序,然后調(diào)用 itertools.groupby() 函數(shù):

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)

運(yùn)行結(jié)果:

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() 函數(shù)掃描整個序列并且查找連續(xù)相同值(或者根據(jù)指定key函數(shù)返回值相同)的元素序列。在每次迭代的時候,它會返回一個值和一個迭代器對象,這個迭代器對象可以生成元素值全部等于上面那個值的組中所有對象。

一個非常重要的準(zhǔn)備步驟是要根據(jù)指定的字段將數(shù)據(jù)排序。因?yàn)?groupby() 僅僅檢查連續(xù)的元素,如果事先并沒有排序完成的話,分組函數(shù)將得不到想要的結(jié)果。

如果你僅僅只是想根據(jù)date字段將數(shù)據(jù)分組到一個大的數(shù)據(jù)結(jié)構(gòu)中去,并且允許隨機(jī)訪問,那么你最好使用 defaultdict() 來構(gòu)建一個多值字典,關(guān)于多值字典已經(jīng)在1.6小節(jié)有過詳細(xì)的介紹。比如:

from collections import defaultdict
rows_by_date = defaultdict(list)
for row in rows:
    rows_by_date[row['date']].append(row)

這樣的話你可以很輕松的就能對每個指定日期訪問對應(yīng)的記錄:

>>> 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'}
>>>

在上面這個例子中,我們沒有必要先將記錄排序。因此,如果對內(nèi)存占用不是很關(guān)心,這種方式會比先排序然后再通過 groupby() 函數(shù)迭代的方式運(yùn)行得快一些。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號