1.1 将序列分解为单独的变量
p=(4,5)
x,y=p
只要对象是可迭代的,就可以执行分解操作。
字符串、文件、迭代器、生成器都可以。
字符串:
s='hello'
a,b,c,d,e=s
想要丢弃特定的值,使用一个用不到的变量名就可以了。
1.2 从任意长度的可迭代对象中分解元素
first,*middle,last=grades
*middle代表了中间的n个元素。
可以用在递归算法,不过python不推荐使用递归。
1.3 保留最后n个元素
这里可以使用队列collections.deque。
有append(),pop(),appendleft(),popleft()几种常用方法。
1.4 找到最大或者最小的n个元素
可以使用nlargest()和nsmallest(),这两个函数可以使用key,即lambda表达式。
当待排序元素总数过大时,应该采用heapq(堆排序),获得最佳性能。
如果只想找一个最大/最小元素,可以使用min(),max()。
1.5 实现优先级队列
可以使用堆排序来实现,参考heapq。
heapq.heappush()负责向堆中加入元素
heapq.heappop()返回最小的元素
优先级队列中的元素采用(-priority,index,item)数据结构实现,优先级取负值因为heap是由小到大排序,index是为了优先级相同的元素依然可以正确排序。
1.6 字典中将键映射到多个值上
在字典item中嵌套容器,如:
d={
'a':[1,2,3],
'b':{4,5}
}
为了方便的创建这样的字典,我们使用collections.defaultdict类。
d=defaultdict(list)
d['a'].append(1)
当然,也可以使用普通字典的setdefault():
d={}
d.setdefault('a',[]).append(1)
1.7 让字典保持有序
使用collections.OrderDict,有序的字典,内部维护双向链表,内存开销很大。
1.8 与字典有关的计算问题
在对字典内容排序时,需要先用zip()将键值对翻转过来,如:
min_price=min(zip(prices.values(),prices.keys()))
如果需要排序,zip配合sort。
请注意,zip所创建的是一个迭代器,它的内容只能使用一次。
1.9 在两个字典中寻找相同点
寻找相同的键:
a.keys() & b.keys()
a.keys()-b.keys()
寻找相同的值:
a.items & b.items()
keys()方法会返回keys-view对象,支持集合操作。
items()方法会返回items-view对象,支持集合操作。
但是values()方法不支持集合操作。
1.10 从序列中移除重复项且保持元素间顺序不变
先说明一下可哈希:
简单的说就是不可变,如数值,字符串,元组,frozenset之类的,而列表、字典、集合之类的就不行。
如果序列中的值是可哈希的,可以使用集合实现:
def dedupe(items):
seen=set()
for item in items:
if item not in seen:
yield item
seen.add(item)
a=[1,1,2,3,4,5,4]
list(dedupe(a))
如果存在不可哈希的对象,
def dedupe(items):
seen=set()
for item in items:
val=item if key is None else key(item)
if val not in seen:
yield item
seen.add(val)
a=[1,1,2,3,4,5,4]
list(dedupe(a))
其实,也可以直接set(a),来获得一个集合。但是这样做会打乱原有顺序。
1.11 对切片命名
record='..........11........22'
SHARES=slice(10,11)
PRICE=slice(20,21)
cost=int(record[SHARES])*int(record[PRICE])
在平面文件处理中比较常用,如文件读取。对于切片对象,有start(),stop(),step()函数可以使用。
1.12 找出序列中出现次数最多的元素
collections中的Counter类和most_common()方法可以解决。
from collections import Counter
word_counts=Counter(words)
top_three=word_counts.most_common(3)
如果需要增加计数,可以使用update()方法
Counter也可以与数学运算结合起来
1.13 通过公共键对字典列表排序
利用operator模块中的itemgetter函数对这类结构进行排序。同样可用于min、max。
from operator import itemgetter
row_by_name=sorted(rows,key=itemgetter('fname'))
1.14 对不原生支持比较操作的对象排序
可以使用operator的attrgetter模块。同样可用于min、max。
sorted(users,key=attrgetter('user_id'))
使用itertools.groupby()函数。
from operator import itemgetter
from itertools import groupby
rows.sort(key=itemgetter('date'))
for date,items in groupby(rows,key=itemgetter('date')):
print date
for i in items:
print (' ',i)
注意:groupby只能检查连续的项,所以要先排序。
1.16 筛选序列中的元素
可以使用列表推导式,例如:
mylist=[1,2,3,4,5]
[n for n in mylist if n>3]
但是这样内存占用会过大。可以使用生成器表达式:
pos=(n for n in mylist if n>4)
for x in pos:
print(x)
对于复杂的逻辑,可以使用filter()+筛选逻辑函数:
val=['1','2','x','-']
def is_int(val):
try:
x=int(val)
return True
except ValueError:
return False
ivals=list(filter(is_int,val))
print (ivals)
1.17 从字典中提取子集
可以利用字典推导式:
prices={
'aaa':1,
'bbb':2
}
p1={key:value for key,value in prices.items() if value>1}
1.18 将名称映射到序列的元素中
我们使用collections.namedtuple():
from collections import namedtuple
Subscriber= namedtuple('Subscriber',['addr','joined'])
sub=Subscriber('111@qq.com','2012-1-1')
使用方法与字典基本一致,注意它是不可变的,修改属性需要用_replace()方法来实现。
上述方法可以用于处理缺失字段的命名元组。
1.19 同时对数据做转换和换算
可以在函数参数中使用生成器表达式
num=[1,2,3,4,5]
sum(x*x for x in num)
sum([x*x for x in num])
注意,上下两个语句是不一样的,上边只使用生成器表达式,下面使用了列表表达式,多了一个步骤,创建额外的列表(只使用一次就作废)。
1.20 将多个映射合并为单个映射
使用collections.ChainMap():
a={
'a':1,
'b':2
}
b={
'c':3,
'd':4
}
from collections import ChainMap
c=ChainMap(a,b)
如果a、b有重复的值,采用第一个的。
修改操作出现在第一个映射结构上。