當前位置:
首頁 > 知識 > Python 標準庫精華: collections.Counter

Python 標準庫精華: collections.Counter

Python 標準庫精華: collections.Counter

這裡有個好玩的問題。給定一個不同國家的電話號碼庫,確定每個國家中最普遍的顯示格式,並使用它重新格式化這個國家的任意電話號碼。例如,如果我們的數據語料庫中的大多數美國電話號碼都寫成xxx-xxx -xxxx,那麼字元串(206)1234567就應該轉換為206-123-4567。

為了簡單起見,我們假設所有的電話號碼都是不包含國別前綴的。

轉換

實際的轉換並不是這篇文章的主題,但是為了完整起見,這裡有兩個補充的函數,一個確定模式,另一個根據模式格式化電話號碼:

Python 標準庫精華: collections.Counter

(為了清晰起見省略了錯誤處理。)

簡單的解決方案

通常的方法是使用類似於字典的結構,它將模式作為鍵保存,並計算模式在源資料庫中出現的頻率,因此結果有點類似於這樣:

Python 標準庫精華: collections.Counter

(不要介意數字,這是一個小資料庫!)

據我所知,在這種情況下,人們通常會使用defaultdict。它在第一次訪問時會自動初始化不存在的鍵值,你每次只需要執行result[key] += 1 即可。在我們的例子中,我們需要一個更複雜的東西: 一個defaultdict 用於存儲country,它將使用嵌套的defaultdict 來初始化計數的鍵。總的來說它看起來可能是這樣的:

Python 標準庫精華: collections.Counter

Counter(計數器)

這裡有一個經驗法則: 當你看到 defaultdict(int) 時,你可以用一個Counter 替換它。它可以做 defaultdict 所能做的一切,加上一些方便的技巧,比如 .most_common 方法,我們可以使用它來代替前面示例中笨拙的 max 表達式。

Python 標準庫精華: collections.Counter

平鋪和函數

我再為你提供另一個解決方案,那就是更多地使用 Counter 魔法。我還將用函數的方法替換 for 循環,這樣一來 for 循環就不是非要不可:-)

下面是代碼,然後是解釋:

Python 標準庫精華: collections.Counter

看吧,沒有循環了!

讓我來解釋一下這裡發生的一切。

  • 事實上,Counter 可以處理一個平鋪式序列的東西,然後一口氣數完:

Python 標準庫精華: collections.Counter

在我們的例子中,要想實現這一點,我們必須用平面數據結構替換嵌套數據結構。這可以通過簡單地將鍵值粘合在一個元組中, 並用等效的 stats[(country, pattern)] 替換 stats[country][ pattern] (你可以對任意數量的鍵執行此操作)來實現。

  • 表達式(country, get_pattern(phone)) for country, phone in db 看起來像一個沒有方括弧的列表推導。實際上,它是一個生成器表達式,你可以遍歷它而不需要在內存中構造一個實際的列表。它通常用括弧括起來( ... ),但是當它是一個函數調用中的唯一參數時,你可以省略它們,並避免使用像 Counter((..)) 這樣醜陋的重複。

  • stats.most_common 在沒有參數的情況下會將結構的全部內容作為一個排好序的 (key, count) 列表返回:

Python 標準庫精華: collections.Counter

它是按計數排序的,不考慮country,但是我們不關心這個,你稍後會看到這些,以及為什麼我們需要反轉它。

  • 最後的表達式是一個字典推導,它遍歷已排序的列表,使用(country, pattern),_ 模擬一個鍵對的結構,將列表中嵌套的鍵對分解為單個變數。_ 是我們不使用的東西的慣例名稱,在我們的例子中就是count。因此,我們實際轉換成的最終字典序列是這樣的,country變成鍵,模式變成值:

Python 標準庫精華: collections.Counter

  • 重要的是:具有相同鍵的後續值會替換字典中已經存在的值。這就是為什麼我們需要反轉列表的原因,所以我們就用計數較大的模式替換最不常見的模式。這也是為什麼我們不關心country之間的混合,因為它們不會相互影響。

誠然,最後一點是最不明顯的。

這是不是更好一點?

我並不在乎,你可以自己判斷:-) 我只是想實際的展示一下collections.Counter!

工作代碼作為福利送給你: phone-counter.py(http://softwaremaniacs.org/media/blog/phone-counter.py)。


英文原文:http://softwaremaniacs.org/blog/2019/03/09/collections-counter/en/
譯者:憂鬱的紅秋褲

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Python部落 的精彩文章:

數據可視化-使用Python進行圖表疊加
Windows 10版本1903中的WSL有什麼新特性?

TAG:Python部落 |