python 食谱-day01

  • 一、 需求:排除list的第一个以及最后一个元素之后,进行平均数的求解
def avg(agrs):
    return  sum(agrs)/len(agrs)

def drop_first_last(grades):
    first, *middle, last = grades
    return avg(middle)

print(drop_first_last((1, 2, 3, 4, 5, 6, 7, 8, 9)))

输出:5.0

注意middle变量永远都是列表类型,不管中间有多少(包括0),所以任何使用到middle变量的代码就不需要做多余的类型检查去确认它是否是列表类型了.

  • 二、从一个集合中获得最大或者最小的N个元素列表
    heaps模块有两个函数:nlargest()smallest()可以解决这个问题
import  heapq
nums = [1,8,2,23,7,-4,18,23,42,37,2]
print(heapq.nlargest(3,nums))#获取最大的前3个数
print(heapq.nsmallest(4,nums))

[42, 37, 23]
[-4, 1, 2, 2]

两个函数都能狗解手一个关键字参数,用于更复杂的数据结构

import heapq
portInfo = [
    {'name':'IBM','shares':100,'price':91.1},
    {'name':'APPLE','shares':50,'price':543.22},
    {'name':'FB','shares':200,'price':21.09},
    {'name':'HPQ','shares':35,'price':31.75},
    {'name':'YHOO','shares':45,'price':16.35},
    {'name':'ACME','shares':75,'price':115.65},
]

expensive = heapq.nlargest(3,portInfo,key=lambda s:s['price'])
cheap = heapq.nsmallest(3,portInfo,key=lambda s : s['shares'])
print(expensive)
print(cheap)
# key = lambda  s: s['price']
# print(key(portInfo[1]))

在上面的代码对每个元素进行对比的时候,会以price的值进行比较

[{'shares': 50, 'name': 'APPLE', 'price': 543.22}, {'shares': 75, 'name': 'ACME', 'price': 115.65}, {'shares': 100, 'name': 'IBM', 'price': 91.1}]
[{'shares': 35, 'name': 'HPQ', 'price': 31.75}, {'shares': 45, 'name': 'YHOO', 'price': 16.35}, {'shares': 50, 'name': 'APPLE', 'price': 543.22}]

如果你想在一个集合中查找最小或最大的N个元素,并且N小于集合元素数量,那么这些函数提供了很好的性能。因为在底层实现里边,首先会将集合数据进行堆排序后放入一个列表中:

nums = [1,4,5,2,6,7,2,6,7,1,2,9]
heapq.heapify(nums)
print(nums)

注意heapq.heapify(nums)这个操作并没有返回值

[1, 1, 2, 2, 2, 7, 5, 6, 7, 6, 4, 9]

堆数据结构最重要的特征是heap[0]永远是最小的元素,并且剩余的元素可以很容易通过调用heapq.heappop()方法得到,该方法会先将第一个元素弹出来,然后用下一个最小的元素来取代被弹出元素(成为最小的元素,这种操作时间复杂度为O(N),N是堆大小)

当要查找的元素个数相对比较小的时候,函数nlargest()nsmallest()是很合适的。如果你仅仅想查找唯一的最小或最大(N=1)的元素的话,那么使用min()max()函数会更快些。类似的,如果N的大小和集合大小接近的时候,通常先排序这个集合然后在使用切片操作会更快点(sorted(items)[:N]或者是sorted(items)[-N:])。

  • 1.6 怎样实现一个键对应多个值得字典(也叫 multidict)

解决方案:一个字典就是一个键对应一个单值的映射。如果你想要一个键映射多个值,那么你就需要将这多个值放到另外的容器中,比如列表或者集合里边,你可以像下面这样构造这样的字典

d = {
    'a':[1,2,3],
    'b':[4,5],
    'c':[6,7,8,9]
}

e = {
    'a':{1,2,3},
    'b':{4,5},
    'c':{6,7,8,9}
}

print(d)
print(e)

我发现一个奇怪的现象,就这这两个输出语句同时打印的话,输出是有序的,两个都是有序的,如果分开只打印一句的话,就是乱的,当然,列表的内部是有序的
选择使用列表还是集合取决于你的实际需求,如果你想保持元素的插入顺序就应该使用列表,如果你想去掉重复元素就使用集合(并且不关心元素的顺序问题)

1.7字典排序

问题:你想创建一个字典,并且在迭代或序列化这个字典的时候能够控制元素的顺序。
  解决方案:为了控制一个字典中元素的顺序,你可以使用collections模块中的OrderedDict类。在迭代操作的嘶吼它会保持元素被插入时的顺序,示例如下:

from collections import OrderedDict
def order_dict():
    d = OrderedDict()
    d['bar'] = 2
    d['grok'] = 4
    d['foo'] = 1
    d['spam'] = 3
    for k in d:
        print(k,d[k])

    # for (k,v) in d.items():
    #     print(k,v)
order_dict()

bar 2
grok 4
foo 1
spam 3

  • 当你想要构建一个将来需要序列化或编码成其他格式的映射的时候,OrderedDict是非常有用的。比如你想精确控制以JSON编码后字段的顺序,你可以先使用OrderedDict来构建这样的数据

import json
from collections import OrderedDict
d = OrderedDict()
d['bar'] = 2
d['grok'] = 4
d['foo'] = 1
d['spam'] = 3
print(d)
print(json.dumps(d))

>OrderedDict([('bar', 2), ('grok', 4), ('foo', 1), ('spam', 3)])
{"bar": 2, "grok": 4, "foo": 1, "spam": 3}

`OrderedDict`内部维护着一个根据键插入顺序排序的双向链表。每次当一个新的元素插入进来的时候,它会被放到链表的尾部。对于一个已经存在的键的重复赋值不会改变键的顺序。需要注意的是,一个 `OrderedDict`的大小是一个普通字典的两倍,因为它内部维护着另一个链表。所以如果你需要构建一个需要大量`OrderedDict`实例的数据结构的时候(比如读取100000行CSV数据到一个OrderedDict列表中去),那么就得考虑一下`OrderedDict`带来的好处与额外内存消耗了。

#####   1.8字典的运算
 怎么在数据字典中执行一些计算操作(比如求最小值、最大值、排序等等)?

prices = {
'ACME':45.23,
'APPL':612.78,
'IBM':205.55,
'HPQ':37.20,
'FB':10.75
}

print(prices)
print(min(zip(prices.values(),prices.keys())))
print(min(zip(prices.keys(),prices.values())))

为了对字典值执行计算操作,通常需要使用`zip()`函数。。。。关于zip(),未完待续。。。。

  * 同样的,可以结合`zip()` 和`sorted()`函数来排列字典

prices_sorted = sorted(zip(prices.values(),prices.keys()))
print(prices_sorted)

> [(10.75, 'FB'), (37.2, 'HPQ'), (45.23, 'ACME'), (205.55, 'IBM'), (612.78, 'APPL')]

* 需要注意的是`zip()`函数创建的是一个只能访问一次的迭代器。

prices_and_names = zip(prices.values(),prices.keys())
print(min(prices_and_names))
print(max(prices_and_names))#这里就会报错如下:

>(10.75, 'FB')
Traceback (most recent call last):
  File "/Users/mudy/Documents/Python/Fishc/day01.py", line 160, in <module>
    print(max(prices_and_names))
ValueError: max() arg is an empty sequence

* 1.9查找两字典的相同点
&emsp;&emsp;怎么在两个字典中寻找相同点(比如相同的键,相同的值)

a = {
'x' : 1,
'y' : 2,
'z' : 3,
}

b = {
'w' : 10,
'x' : 11,
'y' : 2
}

print(a.keys() & b.keys())#AB同时存在的key
print(a.keys()-b.keys())#在A不在B里的
print(a.items()&b.items())#AB中同时存在的元素

>{'y', 'x'}
{'z'}
{('y', 2)}

你还可以这么的,假如你想以现有字典构造一个排除几个指定键的新字典。

c = {key:a[key] for key in a.keys()-{'z'}} #列表生成式
print(c)

>{'y': 2, 'x': 1}

##### 1.10删除序列相同元素并保持顺序
&emsp;怎样在一个序列上面保持元素顺序的同事消除重复的值。

关于`yield`可以看[这篇文章](https://www.oschina.net/translate/improve-your-python-yield-and-generators-explained)
`return隐含的意思是函数正将执行代码的控制权返回给函数被调用的地方。而"yield"的隐含意思是控制权的转移是临时和自愿的,我们的函数将来还会收回控制权。`
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容