python中的enumerate、map、filter和zip函数
引入
python内置了很多可以供我们直接调用的函数,这些函数的效率往往都非常高。我们在自己造轮子的同时,也非常有必要了解并且正确使用python给我们提供的大量的内置函数。在前面的博客里面我已经介绍了collections模块里面的几个比较常用的函数,这里再介绍几个。
1.enumerate
enumerate(iterable, start=0) :对指定的对象进行枚举
返回一个枚举对象。 iterable 必须是一个序列,或 iterator ,或其他支持迭代的对象。 enumerate() 返回的迭代器的 __next__() 方法返回一个元组,里面包含一个计数值(从 start 开始,默认为 0)和通过迭代 iterable 获得的值。
注: iterable 指的是可迭代对象, iterator 指的是迭代器,需要注意的是可迭代对象不一定是迭代器,而迭代器一定是可迭代对象,迭代器需要实现 __next__() 方法。
例:
names = ['zhangsan', 'lisi', 'wangwu'] print(list(enumerate(names))) # [(0, 'zhangsan'), (1, 'lisi'), (2, 'wangwu')] print(list(enumerate(names, start=1))) # [(1, 'zhangsan'), (2, 'lisi'), (3, 'wangwu')]
相当于:
def enumerate(sequence, start=0): n = start for elem in sequence: yield n, elem n += 1
2.map
map(function, iterable, …) : 作用是将一个列表映射到另一个列表
对参数 iterable 中每个元素都调用funcion(函数),并返回输出其结果的迭代器。 如果传入了额外的 iterable 参数,function必须接受相同个数的实参。 当有多个可迭代对象时,最短的可迭代对象耗尽则整个迭代就将结束。
例1:
print(list(map(lambda x:x+1,[1,2,3]))) # [2, 3, 4]
注意:因为返回的是可迭代对象,所以需要调用list来显示。
例2:
def add(n, m): return n + m lst = list(map(add, [1, 2, 3], [1, 2, 3])) print(lst) # [2, 4, 6]
例3:
# map(x, y) 返回x的y次幂 lst = map(pow, [1, 2, 3], [1, 2, 3]) print(list(lst)) # [1, 4, 27]
3.filter
filter(function, iterable) :对指定序列执行过滤操作
filter函数会对序列参数 iterable 中的每个元素调用function函数,最后返回的结果包含调用结果为True的元素。
返回一个迭代器,需要用list调用来显示所有结果。
例1:
print(list(filter((lambda x: x>0), range(-5, 5)))) # [1, 2, 3, 4]
例2:
print(list(fliter(None, range(-2, 2)))) # [-2, -1, 1]
例3:
def func(x): # 返回同时不能被2和3整除的元素 return x % 2 != 0 and x % 3 != 0 print(list(filter(func, range(2,25)))) # [5, 7, 11, 13, 17, 19, 23]
4.zip
zip(*iterables) :用来创建一个聚合了每个可迭代对象中的元素的迭代器。
接受一系列可迭代对象作为参数,将对象中对应的元素打包成一个个tuple,然后返回由这些tuples组成的迭代器。若传入参数的长度不相等,以长度最短的可迭代对象为准。
例1:
print(list(zip([1, 2, 3], [4, 5, 6]))) # [(1, 4), (2, 5), (3, 6)]
例2:
print(list(zip([1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11, 12]))) # [(1, 4, 8), (2, 5, 9), (3, 6, 10)]
应用一矩阵变换:
""" 初始: 1 2 3 4 5 6 7 8 9 变换: 1 4 7 2 5 8 3 6 9 """ matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] print([[row[col] for row in matrix] for col in range(len(matrix[0]))]) # 行变列 # [[1, 4, 7], [2, 5, 8], [3, 6, 9]] print(list(zip(*matrix))) # [(1, 4, 7), (2, 5, 8), (3, 6, 9)] print(list(map(list, zip(*matrix)))) # [[1 ,4 ,7], [2, 5, 8], [3, 6, 9]]
应用二*操作符与zip函数配合可以实现与zip相反的功能,即将合并的序列拆成多个tuple
x=[1,2,3] y=['a','b','c'] print(list(zip(*zip(x,y)))) # [(1,2,3),('a','b','c')]
应用三使用zip合并相邻的列表项
a = [1, 2, 3, 4, 5, 6] print(list(zip(*([iter(a)] * 2)))) # [(1, 2), (3, 4), (5, 6)] group_adjacent = lambda a, k: zip(*([iter(a)] * k)) print(list(group_adjacent(a, 3))) # [(1, 2, 3), (4, 5, 6)] print(list(group_adjacent(a, 2))) # [(1, 2), (3, 4), (5, 6)] print(list(group_adjacent(a, 1))) # [(1,), (2,), (3,), (4,), (5,), (6,)] print(list(zip(a[::2], a[1::2]))) # [(1, 2), (3, 4), (5, 6)] print(list(zip(a[::3], a[1::3], a[2::3]))) # [(1, 2, 3), (4, 5, 6)] group_adjacent = lambda a, k: zip(*(a[i::k] for i in range(k))) print(list(group_adjacent(a, 3))) # [(1, 2, 3), (4, 5, 6)] print(list(group_adjacent(a, 2))) # [(1, 2), (3, 4), (5, 6)]
应用四使用zip和iterators生成滑动窗口 (n -grams)
from itertools import islice def n_grams(a, n): z = (islice(a, i, None) for i in range(n)) return zip(*z) a = [1, 2, 3, 4, 5, 6] print(list(n_grams(a, 3))) #[(1, 2, 3), (2, 3, 4), (3, 4, 5), (4, 5, 6)] print(list(n_grams(a, 2))) #[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)] print(list(n_grams(a, 4))) #[(1, 2, 3, 4), (2, 3, 4, 5), (3, 4, 5, 6)]
应用五使用zip反转字典
m = {'a': 1, 'b': 2, 'c': 3, 'd': 4} print(list(m.items())) #[('a', 1), ('c', 3), ('b', 2), ('d', 4)] print(list(zip(m.values(), m.keys()))) #[(1, 'a'), (3, 'c'), (2, 'b'), (4, 'd')] print(dict(zip(m.values(), m.keys()))) #{1: 'a', 2: 'b', 3: 'c', 4: 'd'}
~>.<~