python进阶——1. 数据结构与算法进阶

1. 筛选数据

  1. 过滤掉列表中的负数
  2. 筛出字典中高于90的项
  3. 筛出集合中能被3整除的元素

可以考虑使用filter函数和列表解析方式:

from random import randint

data_list = [randint(-10, 10) for x in range(10)]
print(data_list)
print(list(filter(lambda x: x >= 0, data_list)))
print([x for x in data_list if x >= 0])

print("=============================================")
data_dict = {x: randint(60, 100) for x in range(10)}
test = {10: 3}
print(data_dict)
print({k: v for k, v in data_dict.items() if v >= 90})

print("=============================================")
data_set = {randint(0, 10) for x in range(10)}
print(data_set)
print({x for x in data_set if x % 3 == 0})

两种方法都可以,但是列表解析速度更快,是首选。

2. tuple命名

为了减小存储开销,对于数据量较多,可以使用tuple来存储。例如有很多个学生,学生的信息项都是相同的。调用这些tuple时可能会通过索引来访问具体的值,这样会降低程序的可读性。那么如何为元组中的每个元素命名,提高程序的可读性。

方案一:
定义类似于其他语言的枚举类型,也就是定义一系列数值常量。

方案二:
使用标准库中collections.namedtuple替代内置tuple

from collections import namedtuple

student = namedtuple('student', ['name', 'age', 'sex', 'addr'])

s = student('Dai', '22', 'male', 'beijing')
print(s)
print(s.name)
print(isinstance(s, tuple))

namedtuple是tuple的子类型,只要是使用tuple的都可以使用namedtuple

3. 统计频率

在一个序列中找出出现频率最高的三个元素;
在一个文件中统计出现频率最高的十个单词;

正常的思路就是新建立一个字典,key是序列中所能包含的字母表或者数字表,value都为0,。然后进行迭代,遇到有的项就加1,最后将字典根据value值进行排序,取出最大的三个。
下面介绍的是一种简单的实现,利用collections.Counter

from collections import Counter
from random import randint

data = [randint(0, 20) for _ in range(1, 15)]

print(Counter(data).items())
print(Counter(data).most_common(3))
print(isinstance(Counter(data), dict))
# dict_items([(1, 1), (2, 1), (3, 3), (4, 2), (5, 1), (6, 1), (7, 1), (8, 1), (20, 1), (12, 1), (15, 1)])
# [(3, 3), (4, 2), (1, 1)]
# True

对于字符串来说,可以通过使用正则表达式来将整个资源按照非字母切分成list,然后再调用Counter来计算出想要的值。

import re
zen = """
Beautiful is better than ugly.  
Explicit is better than implicit.  
Simple is better than complex.  
Complex is better than complicated.  
Flat is better than nested.  
Sparse is better than dense.  
Readability counts.  
Special cases aren't special enough to break the rules.  
Although practicality beats purity.  
Errors should never pass silently.  
Unless explicitly silenced.  
In the face of ambiguity, refuse the temptation to guess.  
There should be one-- and preferably only one --obvious way to do it.  
Although that way may not be obvious at first unless you're Dutch.  
Now is better than never.  
Although never is often better than *right* now.  
If the implementation is hard to explain, it's a bad idea.  
If the implementation is easy to explain, it may be a good idea.  
Namespaces are one honking great idea -- let's do more of those!"""
data_zen = re.split("\W+", zen)
print(Counter(data_zen).most_common(10))

# [('is', 10), ('better', 8), ('than', 8), ('to', 5), ('the', 5), ('idea', 3), ('Although', 3), ('it', 3), ('be', 3), ('never', 3)]

4. 字典排序

对字典的value值进行排序;

通过使用内置函数sorted进行排序,效率高。

方案1:
通过zip函数将字典转化成tuple,再进行排序

from random import randint

data = {x: randint(60, 100) for x in "abcdefg"}
print(sorted(data))
print(sorted(zip(data.values(), data.keys())))
# ['a', 'b', 'c', 'd', 'e', 'f', 'g']
# [(60, 'f'), (66, 'b'), (74, 'c'), (80, 'e'), (94, 'a'), (94, 'd'), (96, 'g')]

方案2:
通过指定sorted的key来进行排序

print(sorted(data.items(), key=lambda x: x[1]))
# [('a', 72), ('c', 74), ('e', 78), ('g', 91), ('b', 92), ('d', 94), ('f', 97)]

5. 字典公共键

有多个字典数据,找出其中共有的键。

思路就是通过Set的交集操作,这是效率最高的解决方案。使用viewkeys方法,得到一个字典keys的集合;然后使用map函数,得到所有字典的keys的集合;最后使用reduce函数,取出所有字典的keys的集合的交集。

from random import randint, sample
from functools import reduce

data1 = {x: randint(1, 4) for x in sample("abcdefg", randint(3, 6))}
data2 = {x: randint(1, 4) for x in sample("abcdefg", randint(3, 6))}
data3 = {x: randint(1, 4) for x in sample("abcdefg", randint(3, 6))}
print(data1.keys() & data2.keys() & data3.keys())
print(reduce(lambda a, b: a & b, map(dict.keys, [data1, data2, data3])))

6.字典有序性

在python中默认的字典dict保存数据时是无序的,也就是与数据的插入顺序不同。如果有需要字典内的数据保持有序的情况,可以使用:

from collections import OrderedDict

7.历史记录功能

查询最近用户输入过的值,并且将其结果保存,下次调用依然可以查询。

实现的思路就是使用python的双向队列deque,然后通过pickle将python对象保存成文件。

import os
import pickle
from random import randint
from collections import deque

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

if os.path.exists('history'):
    history = pickle.load(open('history', 'rb'))
else:
    history = deque([], 5)


def guess(k):
    if k == N:
        print('right')
        return True
    if k < N:
        print('less')
    else:
        print('high')
    return False


while True:
    line = input('input number')
    if line.isdigit():
        k = int(line)
        if guess(k):
            history.clear()
            break
        else:
            history.append(k)
    elif line == 'history':
        print(history)
    elif line == 'end':
        pickle.dump(history, open('history', 'wb'), True)
        os._exit(0)

你可能感兴趣的:(python进阶——1. 数据结构与算法进阶)