摘要:以下測試代碼全部基于查找最大或最小的個元素工作中有時會遇到這樣的需求,取出數據中前面的值,或者最后的值。大家如果對堆數據結構感興趣的話,可以繼續進行深入研究,由于我了解的并不深,也沒辦法再展開了。
文章首發于知乎專欄,歡迎關注。
https://zhuanlan.zhihu.com/py...
以下測試代碼全部基于 Python3
1、查找最大或最小的 N 個元素工作中有時會遇到這樣的需求,取出數據中前面 10% 的值,或者最后 10% 的值。
我們可以先對這個列表進行排序,然后再進行切片操作,很輕松的解決這個問題。但是,有沒有更好的方法呢?
heapq 模塊有兩個函數 nlargest() 和 nsmallest() 可以完美解決這個問題。
In [50]: import heapq In [51]: n = [1, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2, 23, 45, 76] In [52]: heapq.nlargest(3, n) Out[52]: [76, 45, 42] In [53]: heapq.nsmallest(3, n) Out[53]: [-4, 1, 2]
如果是取排在前面的 10% 應該怎么做?
heapq.nlargest(round(len(n)/10), n)
而且,使用這兩個函數還會有更好的性能,因為在底層實現里面,會先把數據進行堆排序后放入一個列表中,然后再進行后續操作。大家如果對堆數據結構感興趣的話,可以繼續進行深入研究,由于我了解的并不深,也沒辦法再展開了。
但是也并不是什么時候都是這兩個函數效果更好,比如只取一個最大值或者最小值,那還是 min() 或 max() 效果更好;如果要查找的元素個數已經跟集合元素個數接近時,那還是用 sorted(items)[:N] 更好,具體情況具體分析吧。
2、序列中出現次數最多的元素以前碰到這類問題時,我都會手動創建一個字典,然后以列表中元素作為 key,進而統計出 key 出現的次數,再進行比較得到出現次數最多的元素。
殊不知 collections 中就有專門為這類問題設計的類 Counter,瞬間感覺自己蠢爆了,話不多說,直接上代碼。
In [54]: from collections import Counter In [55]: w = ["a", "b", "c", "d", "a", "a", "b"] In [56]: w_count = Counter(w) In [57]: w_count Out[57]: Counter({"a": 3, "b": 2, "c": 1, "d": 1}) In [58]: w_count["a"] Out[58]: 3 In [59]: top = w_count.most_common(2) In [60]: top Out[60]: [("a", 3), ("b", 2)]
可以看到,Counter 返回的就是一個字典,想知道哪個元素出現幾次,直接取,是不是很方便?
而且還有 most_common 函數,簡直不要太棒。
3、過濾序列元素有一個列表,如下:
In [61]: a = [1, 2, 3, 4, 5, -3]
要求過濾所有負數。需要新建一個列表?直接一行代碼搞定。
In [64]: [n for n in a if n > 0] Out[64]: [1, 2, 3, 4, 5]
如果要把負數替換成 0 呢?
In [67]: [n if n > 0 else 0 for n in a] Out[67]: [1, 2, 3, 4, 5, 0]
但是有時候過濾條件可能比較復雜,這時就需要借助于 filter() 函數了。
values = ["1", "2", "-3", "-", "4", "N/A", "5"] def is_int(val): try: x = int(val) return True except ValueError: return False ivals = list(filter(is_int, values)) print(ivals) # Outputs ["1", "2", "-3", "4", "5"]4、通過某個關鍵字將記錄分組
有下面這個字典:
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() 函數可以解決這個問題,代碼如下:
# 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 {"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() 函數僅僅檢查連續相同的元素,所以在分組之前,一定要先對數據,按照分組字段進行排序。如果沒有排序,便得不到想要的結果。
5、映射名稱到序列元素我常常有這樣的苦惱,就是有一個列表,然后通過下標來取值,取值時很認真的數所需要元素在第幾個,很怕取錯值。取到值后開始下面的運算。
一段時間之后,再看這段代碼,感覺很陌生,已經忘了帶下標的值是什么了,還需要重新看一下這個列表的由來,才找到回憶。
如果能有一個名稱映射到元素上就好了,直接通過名稱就可以知道元素的含義。collections.namedtuple() 函數就可以解決這個問題。
In [76]: from collections import namedtuple In [77]: subscriber = namedtuple("Subscriber", ["addr", "joined"]) In [78]: sub = subscriber("jonesy@example.com", "2012-10-19") In [79]: sub Out[79]: Subscriber(addr="jonesy@example.com", joined="2012-10-19") In [80]: sub.addr Out[80]: "jonesy@example.com" In [81]: sub.joined Out[81]: "2012-10-19"
這樣就可以通過名稱來取值了,代碼可讀性也更高。
需要注意的是,這種命名元祖的方式不能直接修改其中的值,直接修改會報錯
In [82]: a = namedtuple("SSS", ["name", "shares", "price"]) In [83]: _a = a("yongxinz", 1, 2) In [84]: _a.shares = 4 ----------------------------------------------------------------------- AttributeError Traceback (most recent call last)in () > 1 _a.shares = 4 AttributeError: can"t set attribute
想要修改的話可以使用 _replace() 函數。
In [85]: _a._replace(shares=4) Out[85]: SSS(name="yongxinz", shares=4, price=2)
但是還有一個疑問,如果這個列表元素比較多的話,那就需要定義很多的名稱,也比較麻煩,還有更好的方式嗎?
未完待續。。。
歡迎留言,或添加我個人微信 zhangyx6a 交流,不是微商。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/44511.html
摘要:提供了大量的內置數據結構,包括列表,集合以及字典。這個問題很簡單,我的第一反應是循環求和,然后計算平均值,顯然很麻煩。這時候就該登場了,它的作用是可以使鍵和值反轉過來。 文章首發于知乎專欄,歡迎關注。https://zhuanlan.zhihu.com/py... 以下測試代碼全部基于 Python3。 Python 提供了大量的內置數據結構,包括列表,集合以及字典。在工作和編碼中,可...
摘要:整個過程還是比較清晰的,關鍵是要理解的工作方式,而不是想當然地認為調用了父類的方法。小結事實上,和父類沒有實質性的關聯。 super() 的入門使用 在類的繼承中,如果重定義某個方法,該方法會覆蓋父類的同名方法,但有時,我們希望能同時實現父類的功能,這時,我們就需要調用父類的方法了,可通過使用 super 來實現,比如: class Animal(object): def __...
摘要:鏈接中文翻譯常用庫推薦除了上面提到的之外,也是一個很好的選項。官網中文翻譯如果你要編寫簡單的爬蟲,來爬去互聯網上的信息,或者調用一些外部的機遇的接口,使用這個庫再也合適不過了。 作者:安龍 LeanCloud 工程師 引言 :前段時間有同學反映 Python 的學習資源匯總很少。那么學習資料哪個質量更好,效率更高?Python 有哪些非常值得學習的庫?2017 年了學 2 還是學 3 ...
摘要:過濾字符串中不屬于指定集合的字符任務給定一個需要保留的字符的集合,構建一個過濾函數,并可將其應用于任何字符串,函數返回一個的拷貝,該拷貝只包含指定字符集合中的元素。用方法用于創建字符映射的轉換表,具體代碼如下測試用例測試結果 1.過濾字符串中不屬于指定集合的字符 任務:給定一個需要保留的字符的集合,構建一個過濾函數,并可將其應用于任何字符串s,函數返回一個s的拷貝,該拷貝只包含指定字...
摘要:的三種數據類型字典列表元組,分別用花括號中括號小括號表示。約等于上句,可能是因為自定義變量名與內部函數或變量同名了。下,默認路徑一般為。的日志模塊中計時器定時器計劃任務,。對象的問題怎樣忽略警告不打印煩人的警告打印到終端同時記錄到文件。 Python Enhancement Proposal。(PEP,Python增強建議書) Python之禪(import this) Pytho...
閱讀 3714·2021-11-23 09:51
閱讀 1372·2021-11-10 14:35
閱讀 4012·2021-09-22 15:01
閱讀 1285·2021-08-19 11:12
閱讀 384·2019-08-30 15:53
閱讀 1695·2019-08-29 13:04
閱讀 3434·2019-08-29 12:52
閱讀 3060·2019-08-23 16:14