- 一、 需求:排除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查找两字典的相同点
  怎么在两个字典中寻找相同点(比如相同的键,相同的值)
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删除序列相同元素并保持顺序
 怎样在一个序列上面保持元素顺序的同事消除重复的值。
关于`yield`可以看[这篇文章](https://www.oschina.net/translate/improve-your-python-yield-and-generators-explained)
`return隐含的意思是函数正将执行代码的控制权返回给函数被调用的地方。而"yield"的隐含意思是控制权的转移是临时和自愿的,我们的函数将来还会收回控制权。`