python進階:第一章(數(shù)據(jù)結(jié)構(gòu)與算法)

問題一:如何在列表,字典姨伟,集合中根據(jù)條件篩選數(shù)據(jù)?

問題內(nèi)容:
如何找出列表中的負數(shù)闷供?
如何篩選出字典中值大于某個數(shù)值的項烟央?
如何篩選出集合中能夠被3整除的元素?

解決方案:
對于列表可以使用filter函數(shù)和列表解析:

>>> from random import randint 
>>> data = [ randint(-10,10) for _ in range(10)] 
>>> data 
[-4, 0, 8, -2, -5, -9, 6, 5, 6, 6]
>>> filter(lambda x: x >=0,data) 
<filter object at 0x7f51e28c0c18>
我們看到返回的不是一個列表歪脏,這是python3對filter函數(shù)的修改疑俭,需要使用list()函數(shù)轉(zhuǎn)換。
>>> list(filter(lambda x: x >=0,data)) 
[0, 8, 6, 5, 6, 6]
>>> [ x for x in data if x>= 0] 
[0, 8, 6, 5, 6, 6]

上面的兩個方法中婿失,列表解析耗費的時間要比filter()函數(shù)的少钞艇。

對于字典使用字典解析:

生成一個字典
>>> d = { x: randint(60,100) for x in range(1,21)} 
>>> d
{1: 97, 2: 100, 3: 62, 4: 66, 5: 87, 6: 89, 7: 66, 8: 79, 9: 96, 10: 76, 11: 81, 12: 61, 13: 100, 14: 90, 15: 94, 16: 74,
 17: 80, 18: 76, 19: 81, 20: 82}
查詢出所有值大于90的
>>> {k:v for k,v in d.items() if v>90} 
{1: 97, 2: 100, 15: 94, 13: 100, 9: 96}

對于集合使用集合解析:

>>> s = set(data) 
>>> { x for x in s  if x % 3 ==0}
{0, 6, -9}

問題二:如何為元組中的每個元素命名,提高程序的可讀性豪硅?

問題內(nèi)容:
學(xué)生信息系統(tǒng)中數(shù)據(jù)為固定格式:
(名字哩照,年齡,性別懒浮,郵箱地址)

學(xué)生數(shù)量很大為了減小存儲開銷飘弧,對每個學(xué)生信息用元組表示:
('Wex',24,'female','wex@qq.com')
('Fangyw',23,female,'fangyw@163.com')
('Pandz',25,male,'pandz@qq.com')
......

訪問時,我們使用索引(index)訪問砚著,大量索引降低程序可讀性次伶,如何解決這個問題?

解決方案:
方案一:定義類似與其它語言的枚舉類型稽穆,也就是定義一系列數(shù)值常量冠王。
方案二:使用標準庫中collections.namedtuple替代內(nèi)置tuple

先看使用枚舉:

>>> NAME = 0 
>>> AGE = 1 
>>> SEX = 2 
>>> EMAIL = 3 
>>> student = ('Wex',24,'female','wex@qq.com') 
>>> student[NAME] 
'Wex'

變量的賦值也可以使用列表解包
>>> NAME,AGE,SEX,EMAIL=range(4) 
>>> student[NAME] 
'Wex'

我們接著看使用namedtuple:

首先我們看下namedtuple函數(shù)的用法:
┌──────────────────────────────────────────────────────────────────────────────────────────────┐
│ namedtuple: (typename, field_names, verbose=False, rename=False)                             │
│ Returns a new subclass of tuple with named fields.                                           │
│                                                                                              │
│ >>> Point = namedtuple('Point', ['x', 'y'])                                                  │
│ >>> Point.__doc__                   # docstring for the new class                            │
│ 'Point(x, y)'                                                                                │
│ >>> p = Point(11, y=22)             # instantiate with positional args or keywords           │
│ >>> p[0] + p[1]                     # indexable like a plain tuple                           │
│ 33                                                                                           │
│ >>> x, y = p                        # unpack like a regular tuple                            │
│ >>> x, y                                                                                     │
│ (11, 22)                                                                                     │
│ >>> p.x + p.y                       # fields also accessible by name                         │
│ 33                                                                                           │
│ >>> d = p._asdict()                 # convert to a dictionary                                │
│ >>> d['x']                                                                                   │
│ 11                                                                                           │
│ >>> Point(**d)                      # convert from a dictionary                              │
│ Point(x=11, y=22)                                                                            │
│ >>> p._replace(x=100)               # _replace() is like str.replace() but targets named fie │
│ lds                                                                                          │
│ Point(x=100, y=22)                                                                           │
└──────────────────────────────────────────────────────────────────────────────────────────────┘
該函數(shù)會返回一個內(nèi)置tuple類的子類。第一個參數(shù)是子類的名字舌镶,第二個參數(shù)是索引的名字列表柱彻。

>>> from collections import namedtuple 
>>> namedtuple('Student',['name','age','sex','email']) 
<class '__console__.Student'>
>>> Student = namedtuple('Student',['name','age','sex','email']) 
可以直接使用類創(chuàng)建元組
>>> s1 = Student('Wex',24,'female','wex@qq.com')  
>>> s1 
Student(name='Wex', age=24, sex='female', email='wex@qq.com')
也可以按照屬性名創(chuàng)建
>>> s2 = Student(name='Fyw', age=22, sex='female', email='fyw@qq.com')
>>> s2 
Student(name='Fyw', age=22, sex='female', email='fyw@qq.com')
直接通過屬性獲得值
>>> s1.name 
'Wex'
>>> s2.age 
22
返回的是一個tuple的子類
>>> type(s1) 
<class '__console__.Student'>
>>> isinstance(s1,tuple) 
True

問題三:如何統(tǒng)計列中元素的出現(xiàn)頻度?

問題內(nèi)容:
1餐胀,隨機序列[12,1,2,3,4,5,4,3,4,5,...]中哟楷,找到出現(xiàn)次數(shù)最高的3個元素,它的出現(xiàn)次數(shù)是多少骂澄?
2吓蘑,對某英文文章的單詞進行詞頻統(tǒng)計,找到出現(xiàn)次數(shù)最高的10個單詞坟冲,它們出現(xiàn)的次數(shù)是多少?

對于隨機序列:
使用遍歷的方法:

>>> from random import randint 
創(chuàng)建一段隨機序列
>>> data = [randint(0,20) for _ in range(0,30)] 
根據(jù)隨機序列的值為字典的鍵溃蔫,鍵值默認為0 
>>> c = dict.fromkeys(data,0) 
遍歷隨機序列健提,遍歷到的值相應(yīng)的鍵值加一
>>> for x in data:
...     c[x] += 1 
...     
... 
>>> c 
{0: 2, 2: 1, 3: 2, 4: 1, 5: 3, 6: 1, 7: 1, 9: 1, 10: 1, 12: 1, 14: 3, 15: 2, 16: 3, 17: 2, 18: 2, 19: 3, 20: 1}

解決方案:
使用collections.Counter對象
將序列傳入Counter的構(gòu)造器,得到Counter對象是元素頻度的字典
Counter.most_commom(n)方法得到頻度最高的n個元素的列表
首先看下Counter函數(shù)的語法:

┌──────────────────────────────────────────────────────────────────────────────────────────────┐
│ Counter: (*args, **kwds)                                                                     │
│ data                                                                                         │
│ Create a new, empty Counter object.  And if given, count elements                            │
│ from an input iterable.  Or, initialize the count from another mapping                       │
│ of elements to their counts.                                                                 │
│                                                                                              │
│ >>> c = Counter()                           # a new, empty counter                           │
│ >>> c = Counter('gallahad')                 # a new counter from an iterable                 │
│ >>> c = Counter({'a': 4, 'b': 2})           # a new counter from a mapping                   │
│ >>> c = Counter(a=4, b=2)                   # a new counter from keyword args                │
└──────────────────────────────────────────────────────────────────────────────────────────────┘

我們將生成的隨機序列傳入函數(shù)伟叛,返回的是一個統(tǒng)計結(jié)果的字典

>>> from collections import Counter 
>>> c2 = Counter(data)
>>> c2 
Counter({5: 3, 14: 3, 16: 3, 19: 3, 0: 2, 3: 2, 15: 2, 17: 2, 18: 2, 2: 1, 4: 1, 6: 1, 7: 1, 9: 1, 10: 1, 12: 1, 20: 1})
>>> c2[10]
1
>>> c2[5]
3
>>> c2.most_common(3) 
[(5, 3), (14, 3), (16, 3)]

現(xiàn)在我們對一個文件進行詞頻統(tǒng)計:

>>> import re 
將文件讀入為一個字符串
>>> txt = open('vimrc.txt').read()
使用非字符串對文件進行分割
>>> re.split('\W+',txt)
使用Counter函數(shù)對列表進行統(tǒng)計
>>> c3 = Counter(re.split('\W+',txt))
使用most_common統(tǒng)計前十頻度
>>> c3.most_common(10)

問題四:如何根據(jù)字典中值的大小私痹,對字典中的項排序

問題內(nèi)容:
某班英語成績以字典形式存儲為:
{'wex':98,'fyw':97,'xyx':99...}
根據(jù)成績高低,對學(xué)生排名

解決方案:
使用內(nèi)置函數(shù)sorted
1,利用zip將字典數(shù)據(jù)轉(zhuǎn)化元組
2紊遵,傳遞sorted函數(shù)的key參數(shù)

方法一:使用zip轉(zhuǎn)換為元組進行排序

In [1]:  from random import  randint   

In [2]: d = {x: randint(60,100) for x in 'xyzabc'}  
對字典進行排序账千,只有鍵排序
In [3]: sorted(d)  
Out[3]: ['a', 'b', 'c', 'x', 'y', 'z']
我們看對元組進行排序原理,先對第一個元素進行排序
In [4]: (97,'a') > (96,'b') 
Out[4]: True
第一個相同暗膜,再多第二個進行排序
In [5]: (97,'a') > (97,'b') 
Out[5]: False

In [6]: d.keys()  
Out[6]: dict_keys(['x', 'b', 'z', 'y', 'c', 'a'])

In [7]: d.values()   
Out[7]: dict_values([88, 76, 96, 78, 62, 68])

In [8]: zip(d.values(),d.keys())  
Out[8]: <zip at 0x7f3aac585f48>

In [9]: type(d.keys()) 
Out[9]: dict_keys
在python3中匀奏,zip返回的值需要使用list轉(zhuǎn)換
In [10]: list(zip(d.values(),d.keys())) 
Out[10]: [(88, 'x'), (76, 'b'), (96, 'z'), (78, 'y'), (62, 'c'), (68, 'a')]

In [11]: sorted(list(zip(d.values(),d.keys()))) 
Out[11]: [(62, 'c'), (68, 'a'), (76, 'b'), (78, 'y'), (88, 'x'), (96, 'z')]

方法二:傳遞sorted函數(shù)的key參數(shù)

當我們使用items()函數(shù)時,返回的元素列表的第一項并不是值
In [12]: d.items() 
Out[12]: dict_items([('x', 88), ('b', 76), ('z', 96), ('y', 78), ('c', 62), ('a', 68)])
我們可以指定sorted的排序規(guī)則学搜,下面函數(shù)中的key代表排序的元素娃善,x為前面的元素列表,lambda函數(shù)返回的為字典的值
In [13]: sorted(d.items(),key=lambda x: x[1]) 
Out[13]: [('c', 62), ('a', 68), ('b', 76), ('y', 78), ('x', 88), ('z', 96)]

問題五:如何快速找到多個字典中的公共鍵(key)瑞佩?

問題內(nèi)容:
西班牙足球隊甲級聯(lián)賽聚磺,每一輪球員進球統(tǒng)計:
第一輪:{'蘇亞':1,'梅西':2,'本澤馬':1,......}
第二輪:{'蘇亞':2,'貝爾':1,'格里':2,......}
第三輪:{'蘇亞':1,'托爾':2,'貝爾':2,......}
......
統(tǒng)計出前N輪,每場比賽都有進球的球員炬丸。

使用簡單的遍歷:

>>> from random import  randint,sample 
使用sample選出隨機進球的球員
>>> sample('abcdefg',3) 
['b', 'd', 'a']
設(shè)置進球球員為3到6人
>>> sample('abcdefg',randint(3,6)) 
['c', 'd', 'f', 'b', 'a', 'g']
使用字典生成式
>>> s1 = { x: randint(1,4) for x in sample('abcdefg',randint(3,6))} 
>>> s1
{'f': 3, 'e': 3, 'c': 1, 'b': 4, 'g': 2}
>>> s2 = { x: randint(1,4) for x in sample('abcdefg',randint(3,6))} 
>>> s3 = { x: randint(1,4) for x in sample('abcdefg',randint(3,6))} 
>>> s2
{'f': 2, 'd': 1, 'c': 3, 'b': 3, 'g': 4}
>>> s3
{'e': 4, 'c': 3, 'a': 4, 'b': 3}
>>> inlist = []
>>> for k in s1:
...     if k in s2 and  k in s3:
...         inlist.append(k) 
...         
...     
>>> inlist 
['c', 'b']

其他的解決方案:
利用集合(set)的交集操作:
步驟一:使用字典的viewkeys()方法瘫寝,得到一個字典keys的集合(這是python2的做法,python3使用keys()方法獲得所有的鍵)
步驟二:使用map函數(shù)稠炬,得到所有的字典的keys的集合
步驟三:使用reduce函數(shù)焕阿,取得所有字典的keys的集合的交集

只有三輪比賽
>>> s1.keys()
dict_keys(['f', 'e', 'c', 'b', 'g'])
>>> s1.keys() & s2.keys() & s3.keys() 
{'c', 'b'}
當有多輪的時候
>>> map(dict.keys,[s1,s2,s3]) 
<map object at 0x7f0993531c18>
使用map函數(shù)將字典的鍵都一次變?yōu)閘ist
>>> reduce(lambda a,b: a & b,map(dict.keys,[s1,s2,s3])) 
Traceback (most recent call last):
  File "<input>", line 1, in <module>
    reduce(lambda a,b: a & b,map(dict.keys,[s1,s2,s3]))
NameError: name 'reduce' is not defined
在Python 3里,reduce()函數(shù)已經(jīng)被從全局名字空間里移除了,它現(xiàn)在被放置在fucntools模塊里 用的話要 先引
>>> from functools import reduce 
>>> reduce(lambda a,b: a & b,map(dict.keys,[s1,s2,s3]))  
{'c', 'b'}

問題六:如何讓字典保持有序?

問題內(nèi)容:
編程競賽系統(tǒng)酸纲,對參賽選手編程解題進行計時捣鲸,選手完成題目后,把該選手解題用時記錄到字典中闽坡,以便賽后按選手名查詢成績栽惶。(答題時間越短,成績越優(yōu))
{'wex':(2,43).'hmm':(5,43),'fyw':(1,23)......}
比賽結(jié)束后疾嗅,需按排名順序依次打印選手成績外厂,如何實現(xiàn)?

解決方案:
使用collections.OrderedDict
以O(shè)rderedDict替代內(nèi)置字典Dict,依次將選手成績存入OrderedDict

from collections import OrderedDict 
from random import  randint
from time import time  
d = OrderedDict()   
players = list('ABCDEFGH') 
start = time() 
for i in range(8): 
    input()
    p = players.pop(randint(0,7-i)) 
    end = time()
    print(i+1,p,end-start) 
    d[p] = (i+1,end-start) 


print("******")
for k in d:
    print(k,d[k])

輸出結(jié)果

1 G 1.6133077144622803

2 A 1.9757952690124512

3 D 2.3789286613464355

4 F 2.730335235595703

5 B 3.157444715499878

6 H 3.551867961883545

7 C 3.967583179473877

8 E 4.346914291381836
******
G (1, 1.6133077144622803)
A (2, 1.9757952690124512)
D (3, 2.3789286613464355)
F (4, 2.730335235595703)
B (5, 3.157444715499878)
H (6, 3.551867961883545)
C (7, 3.967583179473877)
E (8, 4.346914291381836)

問題七:如何實現(xiàn)用戶的歷史紀錄功能(最多n條)代承?

問題內(nèi)容:
現(xiàn)在我們制作了一個簡單的猜數(shù)字的小游戲汁蝶,添加歷史記錄功能,顯示用戶最近猜過的數(shù)字论悴,如何實現(xiàn)掖棉?

解決方案:
使用容量為n的隊列存儲歷史紀錄
使用標準庫collectios中的deque,它是一個雙端循環(huán)隊列
程序退出前膀估,可以使用pickle將隊列對象存入文件幔亥,再次運行程序時將其導(dǎo)入。

>>> from collections import deque
使用deque創(chuàng)建定長的隊列
>>> q = deque([],5) 
>>> q.append(1)
>>> q.append(2)
>>> q.append(3)
>>> q.append(4)
>>> q.append(5)
>>> q
deque([1, 2, 3, 4, 5], maxlen=5)
>>> q.append(6)
>>> q 
deque([2, 3, 4, 5, 6], maxlen=5)

游戲文本:

from collections import deque 
from random import randint 

N = randint(0,100)
history = deque([],5) 

def guess(k):
    if k == N:
        print('right')
    if k < N:
        print("%s is less-than N" % k)
    else:
        print("%s is greater-than N" % k) 
    return False 

while True:
    line = input("please input a number:")
    if line.isdigit():
        k = int(line)
        history.append(k)
        if guess(k):
            break
    elif line == "history":
        print(list(history))

上面的程序能夠?qū)崿F(xiàn)游戲的功能察纯,并保存五次輸入帕棉。
使用pickle模塊的dump()和load()函數(shù)可以將數(shù)據(jù)保存到文件和從文件中讀取數(shù)據(jù)

>>> import pickle
>>> p = ['ew','ferf'] 
>>> pickle.dump(p,open('historyy','wb'))
>>> q2 = pickle.load(open('historyy','rb'))
>>> q2
['ew', 'ferf']
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末针肥,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子香伴,更是在濱河造成了極大的恐慌慰枕,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,743評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件即纲,死亡現(xiàn)場離奇詭異具帮,居然都是意外死亡,警方通過查閱死者的電腦和手機崇裁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評論 3 385
  • 文/潘曉璐 我一進店門匕坯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人拔稳,你說我怎么就攤上這事葛峻。” “怎么了巴比?”我有些...
    開封第一講書人閱讀 157,285評論 0 348
  • 文/不壞的土叔 我叫張陵术奖,是天一觀的道長。 經(jīng)常有香客問我轻绞,道長采记,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,485評論 1 283
  • 正文 為了忘掉前任政勃,我火速辦了婚禮唧龄,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘奸远。我一直安慰自己既棺,他們只是感情好,可當我...
    茶點故事閱讀 65,581評論 6 386
  • 文/花漫 我一把揭開白布懒叛。 她就那樣靜靜地躺著丸冕,像睡著了一般。 火紅的嫁衣襯著肌膚如雪薛窥。 梳的紋絲不亂的頭發(fā)上胖烛,一...
    開封第一講書人閱讀 49,821評論 1 290
  • 那天,我揣著相機與錄音诅迷,去河邊找鬼佩番。 笑死,一個胖子當著我的面吹牛罢杉,可吹牛的內(nèi)容都是我干的答捕。 我是一名探鬼主播,決...
    沈念sama閱讀 38,960評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼屑那,長吁一口氣:“原來是場噩夢啊……” “哼拱镐!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起持际,我...
    開封第一講書人閱讀 37,719評論 0 266
  • 序言:老撾萬榮一對情侶失蹤沃琅,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后蜘欲,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體益眉,經(jīng)...
    沈念sama閱讀 44,186評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,516評論 2 327
  • 正文 我和宋清朗相戀三年姥份,在試婚紗的時候發(fā)現(xiàn)自己被綠了郭脂。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,650評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡澈歉,死狀恐怖展鸡,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情埃难,我是刑警寧澤莹弊,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站涡尘,受9級特大地震影響忍弛,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜考抄,卻給世界環(huán)境...
    茶點故事閱讀 39,936評論 3 313
  • 文/蒙蒙 一细疚、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧川梅,春花似錦疯兼、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至潮饱,卻和暖如春来氧,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背香拉。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評論 1 266
  • 我被黑心中介騙來泰國打工啦扬, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人凫碌。 一個月前我還...
    沈念sama閱讀 46,370評論 2 360
  • 正文 我出身青樓扑毡,卻偏偏與公主長得像,于是被迫代替她去往敵國和親盛险。 傳聞我的和親對象是個殘疾皇子瞄摊,可洞房花燭夜當晚...
    茶點故事閱讀 43,527評論 2 349

推薦閱讀更多精彩內(nèi)容