<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          一道題讓你從此真正理解Python編程

          共 3628字,需瀏覽 8分鐘

           ·

          2021-12-30 03:29


          ↑?關(guān)注 + 星標(biāo)?,每天學(xué)Python新技能

          后臺回復(fù)【大禮包】送你Python自學(xué)大禮包


          寫下這個題目的時候,腦海里無法抑制地響起了周華健那略帶沙啞的歌聲:

          遠(yuǎn)處傳來那首熟悉的歌,
          那些心聲為何那樣微弱。
          很久不見,你現(xiàn)在都還好嗎?
          有沒有那么一首歌,
          會讓你輕輕跟著和,
          隨著我們生命起伏,
          一起唱的主題歌;
          有沒有那么一首歌,
          會讓你突然想起我,
          讓你歡喜也讓你憂,
          這么一個我……

          音樂結(jié)束,回到正題。近日瀏覽LeetCode,發(fā)現(xiàn)了一道很有意思的小題目。當(dāng)我嘗試用Python解答的時候,居然動用了集合、map函數(shù)、zip函數(shù)、lambda函數(shù)、sorted函數(shù),調(diào)試過程還涉及到了迭代器、生成器、列表推導(dǎo)式的概念。一個看似極為簡單的題目,盡管最終的代碼可以合并成一行,卻幾乎把Python的編程技巧用了一遍,真可謂“細(xì)微之處見精神”!通過這個題目,也許會讓你從此真正理解了Python編程。


          這道題,名為《列表中的幸運數(shù)》。什么是幸運數(shù)呢?在整數(shù)列表中,如果一個數(shù)字的出現(xiàn)頻次和它的數(shù)值大小相等,我們就稱這個數(shù)字為「幸運數(shù)」。例如,在列表[1, 2, 2, 3]中,數(shù)字1和數(shù)字2出現(xiàn)的次數(shù)分別是1和2,所以它們是幸運數(shù),但3只出現(xiàn)過1次,3不是幸運數(shù)。


          明白了幸運數(shù)的概念,我們就來試著找出列表[3, 5, 2, 7, 3, 1, 2 ,4, 8, 9, 3]中的幸運數(shù)吧。這個過程可以分為以下幾個步驟:


          • 找出列表中不重復(fù)的數(shù)字

          • 統(tǒng)計每個數(shù)字在列表中出現(xiàn)的次數(shù)

          • 找出出現(xiàn)次數(shù)等于數(shù)字本身的那些數(shù)字


          第1步,找出列表中不重復(fù)的數(shù)字


          找出列表中不重復(fù)的數(shù)字,也就是去除列表中的重復(fù)元素,簡稱“去重”。去重最簡潔的方法是使用集合。

          >>>?arr?=?[3,5,2,7,3,8,1,2,4,8,9,3]>>> unique = set(arr)>>> unique{1,?2,?3,?4,?5,?7,?8,?9}


          第2步,統(tǒng)計每個數(shù)字在列表中出現(xiàn)的次數(shù)


          我們知道,列表對象自帶一個count()方法,能返回某個元素在列表中出現(xiàn)的次數(shù),具體用法如下:

          >>>?arr?=?[3,5,2,7,3,8,1,2,4,8,9,3]>>> arr.count(8) # 元素8在數(shù)組arr中出現(xiàn)過2次2


          接下來,我們只需要遍歷去重后的各個元素,逐一統(tǒng)計它們各自出現(xiàn)的次數(shù),并保存成一個合適的數(shù)據(jù)結(jié)構(gòu),這一步工作就萬事大吉了。

          >>>?arr?=?[3,5,2,7,3,8,1,2,4,8,9,3]>>> unique = set(arr) # 去除重復(fù)元素>>> pairs = list() # 空列表,用于保存數(shù)組元素和出現(xiàn)次數(shù)組成的元組>>> for i in unique:    pairs.append((i, arr.count(i)))
          >>> pairs[(1, 1), (2, 2), (3, 3), (4, 1), (5, 1), (7, 1), (8, 2), (9, 1)]


          作為新手,代碼寫成這樣,已經(jīng)很不錯了。但是,一個有追求的程序員絕對不會就此自滿、裹足不前。他們最喜歡做的事情就是想盡千方百計消滅for循環(huán),比如使用映射函數(shù)、過濾函數(shù)取代for循環(huán);即便不能拒絕for循環(huán),他們也會盡可能把循環(huán)藏起來,比如藏在列表推導(dǎo)式內(nèi)。這里既然是要對每一個元素都調(diào)用列表的count()這個方法,那就最適合用map函數(shù)取代for循環(huán)了。

          >>>?m?=?map(arr.count,?unique)>>> m>>> list(m) # 生成器可以轉(zhuǎn)成列表[1, 2, 3, 1, 1, 1, 2, 1]>>> list(m) # 生成器只能用一次,用過之后,就自動清理了[]


          map函數(shù)返回的是一個生成器(generator),可以像列表一樣遍歷,但無法像列表那樣直觀地看到各個元素,除非我們用list()把這個生成器轉(zhuǎn)成列表(實際上并不需要將生成器轉(zhuǎn)為列表)。請注意,生成器和迭代器不同,或者說生成器是一種特殊的迭代器,只能被遍歷一次,遍歷結(jié)束,就自動消失了。迭代器則可以反復(fù)遍歷。比如,range()函數(shù)返回的就是迭代器:

          >>>?a?=?range(5)>>> list(a)[0, 1, 2, 3, 4]>>> list(a)[0, 1, 2, 3, 4]


          說完生成器和迭代器,咱們還得回到原來的話題上。使用map映射函數(shù),我們得到了每個元素的出現(xiàn)次數(shù),還需要和對應(yīng)的元素組成一個一個的元組。這時候,就用上zip()函數(shù)了。zip() 函數(shù)創(chuàng)建一個生成器,用來聚合每個可迭代對象(迭代器、生成器、列表、元組、集合、字符串等)的元素,元素按照相同下標(biāo)聚合,長度不同則忽略大于最短迭代對象長度的元素。

          >>>?m?=?map(arr.count,?unique)>>> z = zip(unique, m)>>> z>>> list(z)[(1, 1), (2, 2), (3, 3), (4, 1), (5, 1), (7, 1), (8, 2), (9, 1)]>>> list(z)[]


          很顯然,zip()函數(shù)返回的也是生成器,只能用一次,過后即消失。


          第3步,找出出現(xiàn)次數(shù)等于數(shù)字本身的那些數(shù)字


          有了每個元素及其出現(xiàn)的次數(shù),我們只需要循環(huán)遍歷……不,請稍等,我們?yōu)槭裁匆欢ㄒh(huán)呢?我們只是要把每個元素過濾一遍,找出那些出現(xiàn)次數(shù)等于元素自身的那些元組,為什么不試試過濾函數(shù)filter()呢?

          >>>?def?func(x):?#?參數(shù)x是元組類型    if x[0] == x[1]:      return x
          >>> m = map(arr.count, unique)>>> z = zip(unique, m)>>> f = filter(func, z)>>> f>>> list(f)[(1, 1), (2, 2), (3, 3)]>>> list(f)[]


          過濾函數(shù)filter()接受兩個參數(shù),第1個參數(shù)是個函數(shù),用于判斷一個元素是否符合過濾條件,第2個參數(shù)就是需要過濾的可迭代對象了。filter()函數(shù)返回的也是生成器,只能用一次,過后即消失。


          寫這里,我們幾乎要大功告成了。但是,作為一個有追求的程序員,你能容忍func()這樣一個看起來怪怪的函數(shù)嗎?答案是不能!你一定會用lambda函數(shù)取代它。另外,也許我們還需要對結(jié)果按照元素的大小排序。加上排序,完整代碼如下:

          >>>?arr?=?[3,5,2,7,3,8,1,2,4,8,9,3]>>> unique = set(arr)>>> m = map(arr.count, unique)>>> z = zip(unique, m)>>> f = filter(lambda x:x[0]==x[1], z)>>> s = sorted(f, key=lambda x:x[0])>>> print('幸運數(shù)是:', [item[0] for item in s])幸運數(shù)是:[1, 2, 3]


          終極代碼,一行搞定


          如果你曾經(jīng)有過被那些寫成一行、卻能實現(xiàn)復(fù)雜功能的、看起來像天書一樣的代碼蹂躪的痛苦經(jīng)歷,那么,現(xiàn)在你也可以把上面的代碼寫成一行,去蹂躪別人了。

          >>>?arr?=?[3,5,2,7,3,8,1,2,4,8,9,3]>>> print('幸運數(shù)是:', [item[0] for item in sorted(filter(lambda x:x[0]==x[1], zip(set(arr), map(arr.count, set(arr)))), key=lambda x:x[0])])幸運數(shù)是:[1, 2, 3]


          戲劇性反轉(zhuǎn),這次真的理解Python了!


          有人說,何必那么麻煩呢?這樣寫不是更簡單、更易讀嗎?果然,我真是想多了!

          >>>?arr?=?[3,5,2,7,3,8,1,2,4,8,9,3]>>> [x for x in set(arr) if x == arr.count(x)][1,?2,?3]

          版權(quán)聲明:本文為博主原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接和本聲明。本文鏈接:https://blog.csdn.net/xufive/article/details/105215593


          推薦閱讀

          1. 微信和QQ,終于可以互通了!

          2. 3天,我把數(shù)據(jù)可視化的 Tableau、Excel 透視表擼干凈了!

          3. 2022年春晚小品提前泄露!

          4. 一個小破網(wǎng)站,居然比 Python 官網(wǎng)還牛逼

          5. 阿里瘋傳!Python+商業(yè)數(shù)據(jù)分析+數(shù)據(jù)可視化教程(建議收藏)



          瀏覽 28
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  中文字墓aV | 波多野结衣丝袜无码视频 | 最新国产免费黄色 | 国产一线在线 | 国产精品视频内射 |