Python 通過某個(gè)字段將記錄分組

通過某個(gè)字段將記錄分組


問題


假設(shè)有一個(gè)字典或者實(shí)例的序列,想根據(jù)某個(gè)特定的字段進(jìn)行分組迭代訪問?

解決方法


Python 提供的 itertools 模塊中有個(gè) groupby() 函數(shù),能夠?qū)崿F(xiàn)對(duì)數(shù)據(jù)進(jìn)行分組操作。模擬字典數(shù)據(jù)如下:

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

假設(shè),要以 date 進(jìn)行分組,將分塊的數(shù)據(jù)進(jìn)行迭代。這里首先要對(duì)指定的字段(這里為 date) 進(jìn)行排序 ,然后調(diào)用 groupby() 函數(shù)。

from operator import itemgetter
from itertools import groupby

# 首先以 "date" 進(jìn)行排序
rows.sort(key=itemgetter('date'))
# 遍歷分組后的數(shù)據(jù)塊
for date, items in groupby(rows, key=itemgetter('date')):
    print(date)
    for item in items:
        print(' ', item)

下面是允許后的結(jié)果:

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() 函數(shù)運(yùn)行的機(jī)制是先掃描整個(gè)序列,同時(shí)查找連續(xù)相同值的元素序列。每次迭代返回的結(jié)果,包含一個(gè)值一個(gè)迭代器對(duì)象,這個(gè)迭代器對(duì)象可以生產(chǎn)元素值全部等于上面那個(gè)值的組中所有對(duì)象。

這里需要注意的是,要預(yù)先對(duì)指定的字段進(jìn)行排序。因?yàn)?groupby() 僅僅檢查連續(xù)的元素,如果沒有事先進(jìn)行排序,將達(dá)不到效果。

如果僅僅是根據(jù) date 字段將數(shù)據(jù)分組到一個(gè)大的數(shù)據(jù)結(jié)構(gòu)中,而且可以隨機(jī)訪問。這里可以使用另外一種方法,使用 defaultdict() 構(gòu)建多值字典,示例如下:

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

這個(gè)時(shí)候,就可以根據(jù)指定的日期訪問對(duì)應(yīng)的記錄:

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

這部分代碼無須對(duì)原序列數(shù)據(jù)進(jìn)行排序。這種情況下,這種方式會(huì)比先排序后使用 groupby() 函數(shù)分組再進(jìn)行迭代會(huì)快。

以上為本篇的主要內(nèi)容。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容