1. 程式人生 > >Python資料結構與演算法相關問題與解決技巧

Python資料結構與演算法相關問題與解決技巧

1.如何在列表, 字典, 集合中根據條件篩選資料

from random import randint
data = [randint(-10,10) for _ in range(10)]
data
[4, 4, -5, 6, 7, 10, 5, -7, -6, -9]
# 篩選出列表中大於0的元素

# 使用filter函式
list(filter(lambda x:x>=0,data))
[4, 4, 6, 7, 10, 5]
# 列表解析
[x for x in data if x >= 0]
[4, 4, 6, 7, 10, 5]
timeit list(filter(lambda x:x>=0,data))
1.56 µs ± 33.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
timeit [x for x in data if x >= 0]
625 ns ± 26.2 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
# 字典解析
d = {x:randint(60,100) for x in range(1,21)}
d
{1: 87,
 2: 86,
 3: 97,
 4: 92,
 5: 79,
 6: 90,
 7: 78,
 8: 97,
 9: 63,
 10: 97,
 11: 91,
 12: 69,
 13: 86,
 14: 83,
 15: 84,
 16: 83,
 17: 70,
 18: 86,
 19: 93,
 20: 88}
{k:v for k,v in d.items() if v > 90 }
{3: 97, 4: 92, 8: 97, 10: 97, 11: 91, 19: 93}
# 集合解析
s = set(data)
s
{-9, -7, -6, -5, 4, 5, 6, 7, 10}
{x for x in s if x % 2 == 0}
{-6, 4, 6, 10}

2.如何為元組中的每個元素命名, 提高程式可讀性

#方案一,定義一系列數值常量
NAME,AGE,SEX,EMAIL = range(4)
student = ('Tom','16','male','[email protected]
')
student[NAME]
'Tom'
#方案二,使用namedtuple
from collections import namedtuple
Student = namedtuple('Student',['name','age','sex','email'])
#位置傳參
s = Student('Tom','16','male','[email protected]')
s
Student(name='Tom', age='16', sex='male', email='[email protected]')
#關鍵字傳參
s2 = Student(name='Tom',age='16',sex='male',email='[email protected]')
s2
Student(name='Tom', age='16', sex='male', email='[email protected]')
s.name
'Tom'
s.email
'[email protected]'
isinstance(s,tuple)
True

3.如何統計序列中元素的出現頻度

from random import randint
data = [randint(0,20) for _ in range(30)]
data
[8,
 11,
 16,
 10,
 11,
 10,
 13,
 6,
 20,
 15,
 19,
 13,
 4,
 14,
 8,
 18,
 9,
 8,
 9,
 19,
 11,
 15,
 9,
 4,
 2,
 11,
 11,
 16,
 3,
 19]
#fromkeys:用於建立並返回一個新的字典。兩個引數:第一個是字典的鍵,第二個(可選)是傳入鍵的值,預設為None。
c = dict.fromkeys(data,0)
c
{8: 0,
 11: 0,
 16: 0,
 10: 0,
 13: 0,
 6: 0,
 20: 0,
 15: 0,
 19: 0,
 4: 0,
 14: 0,
 18: 0,
 9: 0,
 2: 0,
 3: 0}
for x in data:
    c[x] += 1
c
{8: 3,
 11: 5,
 16: 2,
 10: 2,
 13: 2,
 6: 1,
 20: 1,
 15: 2,
 19: 3,
 4: 2,
 14: 1,
 18: 1,
 9: 3,
 2: 1,
 3: 1}
# 使用Counter
from collections import Counter
c2 = Counter(data)
c2
Counter({8: 3,
         11: 5,
         16: 2,
         10: 2,
         13: 2,
         6: 1,
         20: 1,
         15: 2,
         19: 3,
         4: 2,
         14: 1,
         18: 1,
         9: 3,
         2: 1,
         3: 1})
#找出頻率出現最高的3個元素
c2.most_common(3)
[(11, 5), (8, 3), (19, 3)]
import re
txt = open('Alice.txt').read()
c3 = Counter(re.split('\W+',txt))
c3
Counter({'Alice': 19,
         'was': 38,
         'beginning': 1,
         'to': 44,
         'get': 5,
         'very': 12,
         'tired': 1,
         'of': 25,
         'sitting': 1,
         'by': 6,
         'her': 15,
         'sisteron': 1,
         'the': 58,
         'bank': 1,
         'and': 44,
         'having': 1,
         'nothing': 5,
         'do': 5,
         'once': 1,
         'or': 9,
         'twice': 1,
         'she': 45,
         'hadpeeped': 1,
         'into': 4,
         'book': 4,
         'sister': 1,
         'reading': 1,
         'but': 14,
         'it': 45,
         'had': 12,
         'nopictures': 1,
         'conversations': 1,
         'in': 17,
         'what': 6,
         'is': 4,
         'use': 3,
         'a': 36,
         'thought': 5,
         'without': 2,
         'pictures': 2,
         'conversation': 1,
         'So': 1,
         'considering': 1,
         'own': 1,
         'mind': 2,
         'as': 13,
         'well': 5,
         'could': 5,
         'for': 11,
         'hot': 3,
         'day': 1,
         'made': 2,
         'feel': 1,
         'sleepy': 2,
         'stupid': 1,
         'whetherthe': 1,
         'pleasure': 1,
         'making': 1,
         'daisy': 1,
         'chain': 1,
         'would': 5,
         'be': 8,
         'worth': 1,
         'troubleof': 1,
         'getting': 3,
         'up': 9,
         'picking': 1,
         'daisies': 1,
         'when': 6,
         'suddenly': 4,
         'WhiteRabbit': 1,
         'with': 10,
         'pink': 1,
         'eyes': 1,
         'ran': 2,
         'close': 2,
         'There': 6,
         'so': 8,
         'VERY': 4,
         'remarkable': 1,
         'that': 18,
         'nor': 1,
         'did': 3,
         'Alicethink': 1,
         'much': 5,
         'out': 8,
         'way': 5,
         'hear': 2,
         'Rabbit': 4,
         'say': 4,
         'toitself': 1,
         'Oh': 4,
         'dear': 3,
         'I': 21,
         'shall': 3,
         'late': 1,
         'thoughtit': 1,
         'over': 3,
         'afterwards': 1,
         'occurred': 1,
         'ought': 1,
         'havewondered': 1,
         'at': 9,
         'this': 8,
         'time': 8,
         'all': 9,
         'seemed': 2,
         'quite': 1,
         'natural': 1,
         'actually': 1,
         'TOOK': 1,
         'A': 1,
         'WATCH': 1,
         'OUT': 1,
         'OF': 1,
         'ITS': 1,
         'WAISTCOAT': 1,
         'POCKET': 1,
         'looked': 3,
         'then': 4,
         'hurried': 1,
         'on': 8,
         'started': 1,
         'toher': 1,
         'feet': 2,
         'flashed': 1,
         'across': 2,
         'neverbefore': 1,
         'seen': 2,
         'rabbit': 3,
         'either': 3,
         'waistcoat': 1,
         'pocket': 1,
         'watch': 1,
         'totake': 1,
         'burning': 1,
         'curiosity': 1,
         'thefield': 1,
         'after': 3,
         'fortunately': 1,
         'just': 3,
         'see': 7,
         'popdown': 1,
         'large': 3,
         'hole': 3,
         'under': 1,
         'hedge': 1,
         'In': 1,
         'another': 3,
         'moment': 2,
         'down': 16,
         'went': 5,
         'never': 1,
         'onceconsidering': 1,
         'how': 6,
         'world': 1,
         'again': 4,
         'The': 2,
         'straight': 1,
         'like': 5,
         'tunnel': 1,
         'some': 1,
         'dipped': 1,
         'not': 13,
         'amoment': 2,
         'think': 9,
         'about': 6,
         'stopping': 1,
         'herself': 3,
         'before': 4,
         'found': 3,
         'herselffalling': 1,
         'deep': 2,
         'Either': 1,
         'fell': 2,
         'slowly': 1,
         'shehad': 1,
         'plenty': 1,
         'look': 1,
         'towonder': 1,
         'going': 2,
         'happen': 1,
         'next': 1,
         'First': 1,
         'tried': 2,
         'lookdown': 1,
         'make': 1,
         'coming': 1,
         'too': 4,
         'dark': 3,
         'tosee': 1,
         'anything': 2,
         'sides': 1,
         'andnoticed': 1,
         'they': 6,
         'were': 6,
         'filled': 1,
         'cupboards': 2,
         'shelves': 2,
         'here': 4,
         'there': 4,
         'saw': 2,
         'maps': 1,
         'hung': 1,
         'upon': 4,
         'pegs': 1,
         'Shetook': 1,
         'jar': 2,
         'from': 3,
         'one': 6,
         'passed': 1,
         'waslabelled': 1,
         'ORANGE': 1,
         'MARMALADE': 1,
         'great': 2,
         'disappointment': 1,
         'itwas': 1,
         'empty': 1,
         'drop': 1,
         'fear': 1,
         'killingsomebody': 1,
         'managed': 1,
         'put': 2,
         'shefell': 1,
         'past': 1,
         'Well': 1,
         'such': 2,
         'fall': 4,
         'Ishall': 1,
         'tumbling': 1,
         'stairs': 1,
         'How': 3,
         'brave': 1,
         'llall': 1,
         'me': 6,
         'home': 1,
         'Why': 1,
         'wouldn': 1,
         't': 4,
         'even': 3,
         'if': 6,
         'off': 4,
         'top': 1,
         'house': 1,
         'Which': 1,
         'likelytrue': 1,
         'Down': 2,
         'Would': 1,
         'NEVER': 1,
         'come': 2,
         'an': 1,
         'end': 1,
         'Iwonder': 1,
         'many': 2,
         'miles': 2,
         've': 2,
         'fallen': 1,
         'said': 3,
         'aloud': 1,
         'must': 1,
         'somewhere': 2,
         'near': 1,
         'centre': 1,
         'earth': 2,
         'Letme': 1,
         'four': 1,
         'thousand': 1,
         'you': 16,
         'learnt': 1,
         'several': 2,
         'things': 1,
         'sort': 2,
         'herlessons': 1,
         'schoolroom': 1,
         'though': 2,
         'goodopportunity': 1,
         'showing': 1,
         'knowledge': 1,
         'no': 6,
         'tolisten': 1,
         'still': 2,
         'good': 1,
         'practice': 1,
         'yes': 1,
         's': 5,
         'right': 2,
         'distance': 1,
         'wonder': 3,
         'Latitudeor': 1,
         'Longitude': 2,
         'got': 2,
         'idea': 1,
         'Latitude': 1,
         'nice': 3,
         'grand': 1,
         'words': 2,
         'tosay': 1,
         'Presently': 1,
         'began': 2,
         'rightTHROUGH': 1,
         'funny': 1,
         'll': 5,
         'seem': 1,
         'among': 1,
         'thepeople': 1,
         'walk': 1,
         'their': 1,
         'heads': 1,
         'downward': 1,
         'Antipathies': 1,
         'Ithink': 1,
         'rather': 1,
         'glad': 1,
         'WAS': 1,
         'listening': 1,
         'thistime': 1,
         'didn': 2,
         'sound': 1,
         'word': 1,
         'shallhave': 1,
         'ask': 2,
         'them': 2,
         'name': 1,
         'country': 1,
         'know': 2,
         'Please': 1,
         'Ma': 1,
         'am': 1,
         'New': 1,
         'Zealand': 1,
         'Australia': 1,
         'triedto': 1,
         'curtsey': 1,
         'spoke': 1,
         'fancy': 1,
         'CURTSEYING': 1,
         're': 1,
         'fallingthrough': 1,
         'air': 2,
         'Do': 3,
         'manage': 1,
         'And': 2,
         'whatan': 1,
         'ignorant': 1,
         'little': 7,
         'girl': 1,
         'asking': 1,
         'No': 2,
         'llnever': 1,
         'perhaps': 1,
         'written': 1,
         'else': 1,
         'soonbegan': 1,
         'talking': 1,
         'Dinah': 5,
         'miss': 1,
         'night': 1,
         'Ishould': 1,
         'cat': 1,
         'hope': 1,
         'rememberher': 1,
         'saucer': 1,
         'milk': 1,
         'tea': 1,
         'my': 3,
         'wish': 1,
         'weredown': 1,
         'are': 1,
         'mice': 1,
         'm': 1,
         'afraid': 1,
         'butyou': 1,
         'might': 3,
         'catch': 1,
         'bat': 1,
         'mouse': 1,
         'But': 1,
         'cats': 4,
         'eat': 5,
         'bats': 3,
         'getrather': 1,
         'saying': 2,
         'dreamy': 1,
         'ofway': 1,
         'sometimes': 1,
         'Dobats': 1,
         'couldn': 1,
         'answer': 1,
         'eitherquestion': 1,
         'matter': 1,
         'which': 2,
         'She': 2,
         'feltthat': 1,
         'dozing': 1,
         'begun': 2,
         'dream': 1,
         'shewas': 1,
         'walking': 1,
         'hand': 2,
         'veryearnestly': 1,
         'Now': 1,
         'tell': 1,
         'truth': 1,
         'ever': 3,
         'abat': 1,
         'thump': 2,
         'came': 3,
         'heap': 1,
         'ofsticks': 1,
         'dry': 1,
         'leaves': 1,
         'bit': 1,
         'hurt': 1,
         'jumped': 1,
         'overhead': 1,
         'herwas': 1,
         'long': 3,
         'passage': 2,
         'White': 1,
         'insight': 1,
         'hurrying': 1,
         'lost': 1,
         'away': 1,
         'wind': 1,
         'itsay': 1,
         'turned': 2,
         'corner': 1,
         'ears': 1,
         'whiskers': 1,
         'lateit': 1,
         'behind': 2,
         'thecorner': 1,
         'longer': 1,
         'foundherself': 1,
         'low': 1,
         'hall': 4,
         'lit': 1,
         'row': 1,
         'lampshanging': 1,
         'roof': 1,
         'doors': 1,
         'round': 3,
         'locked': 1,
         'been': 1,
         'side': 1,
         'theother': 1,
         'trying': 1,
         'every': 1,
         'door': 3,
         'walked': 1,
         'sadly': 1,
         'middle': 1,
         'wondering': 1,
         'Suddenly': 1,
         'three': 1,
         'legged': 1,
         'table': 2,
         'ofsolid': 1,
         'glass': 1,
         'except': 1,
         'tiny': 1,
         'golden': 2,
         'key': 3,
         'first': 1,
         'belong': 1,
         'thedoors': 1,
         'alas': 1,
         'locks': 1,
         'orthe': 1,
         'small': 1,
         'any': 3,
         'rate': 2,
         'open': 1,
         'ofthem': 1,
         'However': 2,
         'second': 1,
         'lowcurtain': 1,
         'noticed': 1,
         'littledoor': 1,
         'fifteen': 1,
         'inches': 1,
         'high': 1,
         'keyin': 1,
         'lock': 1,
         'delight': 1,
         'fitted': 1,
         'opened': 1,
         'led': 1,
         'smallpassage': 1,
         'larger': 1,
         'than': 1,
         'rat': 1,
         'knelt': 1,
         'andlooked': 1,
         'along': 1,
         'loveliest': 1,
         'garden': 1,
         'longed': 1,
         'wander': 1,
         'aboutamong': 1,
         'those': 2,
         'beds': 1,
         'bright': 1,
         'flowers': 1,
         'cool': 1,
         'fountains': 1,
         'butshe': 1,
         'head': 2,
         'doorway': 1,
         'ifmy': 1,
         'go': 1,
         'through': 1,
         'poor': 1,
         'ofvery': 1,
         'shoulders': 1,
         'wishI': 1,
         'shut': 1,
         'telescope': 1,
         'onlyknow': 1,
         'begin': 1,
         'For': 1,
         'thingshad': 1,
         'happened': 1,
         'lately': 1,
         'fewthings': 1,
         'indeed': 1,
         'really': 1,
         'impossible': 1,
         'waiting': 1,
         'shewent': 1,
         'back': 1,
         'half': 1,
         'hoping': 1,
         'find': 1,
         'onit': 1,
         'rules': 1,
         'shutting': 1,
         'people': 1,
         'liketelescopes': 1,
         'bottle': 4,
         'whichcertainly': 1,
         'neckof': 1,
         'paper': 1,
         'label': 1,
         'DRINK': 1,
         'ME': 1,
         'beautifully': 1,
         'printed': 1,
         'letters': 1,
         'It': 1,
         'Drink': 1,
         'wise': 1,
         'littleAlice': 1,
         'THAT': 1,
         'hurry': 1,
         'lookfirst': 1,
         'whether': 1,
         'marked': 3,
         'poison': 3,
         'read': 1,
         'histories': 1,
         'children': 1,
         'whohad': 1,
         'burnt': 1,
         'eaten': 1,
         'wild': 1,
         'beasts': 1,
         'other': 1,
         'unpleasantthings': 1,
         'because': 1,
         'WOULD': 1,
         'remember': 1,
         'simple': 1,
         'rulestheir': 1,
         'friends': 1,
         'taught': 1,
         'red': 1,
         'pokerwill': 1,
         'burn': 1,
         'hold': 1,
         'cut': 1,
         'yourfinger': 1,
         'deeply': 1,
         'knife': 1,
         'usually': 1,
         'bleeds': 1,
         'hadnever': 1,
         'forgotten': 1,
         'drink': 1,
         'almost': 1,
         'certain': 1,
         'disagree': 1,
         'sooner': 1,
         'orlater': 1,
         'NOT': 1,
         'venturedto': 1,
         'taste': 1,
         'finding': 1,
         'fact': 1,
         'sortof': 1,
         'mixed': 1,
         'flavour': 1,
         'cherry': 1,
         'tart': 1,
         'custard': 1,
         'pine': 1,
         'apple': 1,
         'roastturkey': 1,
         'toffee': 1,
         'buttered': 1,
         'toast': 1,
         'soon': 1,
         'finishedit': 1,
         '': 1})
c3.most_common(10)
[('the', 58),
 ('she', 45),
 ('it', 45),
 ('to', 44),
 ('and', 44),
 ('was', 38),
 ('a', 36),
 ('of', 25),
 ('I', 21),
 ('Alice', 19)]

4.如何根據字典中值的大小, 對字典中的項排序

sorted([9,3,1,67,6])
[1, 3, 6, 9, 67]
from random import randint
d = {x:randint(60,100) for x in 'xyzabc'}
d
{'x': 96, 'y': 87, 'z': 86, 'a': 68, 'b': 61, 'c': 75}
d.keys()
dict_keys(['x', 'y', 'z', 'a', 'b', 'c'])
d.values()
dict_values([96, 87, 86, 68, 61, 75])
#方案一:利用zip將字典轉換成元組進行排序
sorted(zip(d.values(),d.keys()))
[(61, 'b'), (68, 'a'), (75, 'c'), (86, 'z'), (87, 'y'), (96, 'x')]
d.items()
dict_items([('x', 96), ('y', 87), ('z', 86), ('a', 68), ('b', 61), ('c', 75)])
#方案二:傳遞sorted函式的key引數
sorted(d.items(),key=lambda x:x[1])
[('b', 61), ('a', 68), ('c', 75), ('z', 86), ('y', 87), ('x', 96)]

5.如何快速找到多個字典中的公共鍵(key)

from random import randint,sample
from random import randint,sample
# 取樣
sample('abcdef',3)
['e', 'd', 'a']
sample('abcdef',randint(3,6))
['a', 'd', 'e', 'c']
# 找出s1,s2,s3中都存在的key

# 方案一:遍歷
s1 = {x:randint(1,4) for x in sample('abcdef',randint(3,6))}
s1
{'c': 1, 'b': 2, 'e': 3, 'd': 3, 'f': 1, 'a': 2}
s2 = {x:randint(1,4) for x in sample('abcdef',randint(3,6))}
s3 = {x:randint(1,4) for x in sample('abcdef',randint(3,6))}
s2
{'a': 3, 'f': 1, 'c': 1, 'b': 2, 'd': 4, 'e': 4}
s3
{'a': 3, 'd': 1, 'e': 1}
res = []
for k in s1:
    if k in s2 and k in s3:
        res.append(k)
res
['e', 'd', 'a']
# 方案二:使用集合
s1
{'c': 1, 'b': 2, 'e': 3, 'd': 3, 'f': 1, 'a': 2}
s1.keys()
dict_keys(['c', 'b', 'e', 'd', 'f', 'a'])
s2.keys()
dict_keys(['a', 'f', 'c', 'b', 'd', 'e'])
s1.keys() & s2.keys() & s3.keys()
{'a', 'd', 'e'}
# 方案三:使用map和reduce

# Python3裡,map返回的結果是迭代器(iterator)
list(map(dict.keys,[s1,s2,s3]))
[dict_keys(['c', 'b', 'e', 'd', 'f', 'a']),
 dict_keys(['a', 'f', 'c', 'b', 'd', 'e']),
 dict_keys(['a', 'd', 'e'])]
from functools import reduce
# reduce() 函式會對引數序列中元素進行累積。
reduce(lambda a,b:a & b,map(dict.keys,[s1,s2,s3]))
{'a', 'd', 'e'}

6.如何讓字典保持有序

d = {}
d['Tom'] = (1,35)
d['Bob'] = (2,37)
d['Kate'] = (3,45)
d
{'Tom': (1, 35), 'Bob': (2, 37), 'Kate': (3, 45)}
# python3.6之後字典有序,按照資料存入的順序
for k in d:
    print(k)
Tom
Bob
Kate
# 有序字典OrderedDict
from collections import OrderedDict
d = OrderedDict()
d['Tom'] = (1,35)
d['Bob'] = (2,37)
d['Kate'] = (3,45)

for k in d:
    print(k)
Tom
Bob
Kate
from time import time
from random import randint
from collections import OrderedDict

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,sep=' ')
    d[p] = (i + 1, end - start)

print('-' * 30)

for k in d:
    print(k, d[k])
1 B 3.176684856414795

2 A 3.636547327041626

3 G 3.978159189224243

4 E 4.341858386993408

5 D 4.702983379364014

6 F 5.248721599578857

7 C 5.690965414047241

8 H 6.034142017364502
------------------------------
B (1, 3.176684856414795)
A (2, 3.636547327041626)
G (3, 3.978159189224243)
E (4, 4.341858386993408)
D (5, 4.702983379364014)
F (6, 5.248721599578857)
C (7, 5.690965414047241)
H (8, 6.034142017364502)

7.如何實現使用者的歷史記錄功能(最多n條)

from collections import deque
# 建立雙向佇列
q = deque([], 5)
q
deque([])
q.append(1)
q.append(2)
q.append(3)
q.append(4)
q.append(5)

q
deque([1, 2, 3, 4, 5])
q.append(6)

q
deque([2, 3, 4, 5, 6])
from random import randint
from collections import deque

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

def guess(k):
    if k == N:
        print('Right')
        return True
    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' or line == 'h':
        print(list(history))
Please input a number:50
50 is less-than N
Please input a number:80
80 is less-than N
Please input a number:90
90 is less-than N
Please input a number:91
91 is less-than N
Please input a number:92
92 is less-than N
Please input a number:93
93 is less-than N
Please input a number:h
[80, 90, 91, 92, 93]
Please input a number:95
95 is greater-than N
Please input a number:94
Right
import pickle
q
deque([2, 3, 4, 5, 6])
# 將資料存入檔案
pickle.dump(q,open('history','wb'))
# 讀取檔案
q2 = pickle.load(open('history','rb'))
q2
deque([2, 3, 4, 5, 6])