借鉴于其他多数语言中集合的 map/reduce 操作,也想总结一下在 Python 中如何对集合进行 map/reduce。而不是对于 Python 集合只会用简单的 for ... in
遍历,处于之间的是 Python 的 Comprehension 操作,更倾向于译作推导; 在 Scala 中也有类似的 for-comprehension
语法。
因此本文将涉及到三个方面的知识,基本的集合遍历操作,集合的推导,与 filter/map/reduce 操作。我无法写出诸如 掌握 Python 集体看这一篇就够了 的文章,但基本由本篇出发能了解到 Python 集合的基本遍历,转换操作。其余如切片,和更多能作用于 Python 集合的函数未有提及, 请查阅相关文档。
集合的基本遍历操作
这一块主要是复习功课, 希望由此熟练掌握常用的集合遍历操作方式
基本遍历
这个 for ... in
语法可应用于 list
, tuple
, 和 set
, 还有 range
, map
等。
不过上面的语法应用于 dict
只是对 key
进行遍历
对于 dict 既然可以对 keys()
进行遍历,也就可以对值 values()
进行遍历
x.keys()
的类型是 dict_keys
,list(x.keys()
可以得到所有 key 组成的 list
。set(x.keys()
得到相应的 set
x.values()
的类型是 dict_values
。也可以用 list(x.values()
和 set(x.values()
转换为相应的 list
和 set
对 dict
同时遍历 key, value
map.items()
类型是 dict_items
, 看下方
因为每个元素是由 (key, value) 组成的 tuple
, 所以能用 for key, value
进行拆解(unpack)。
遍历时得到索引
这时候要用到 enumerate
函数
可以想像它实质遍历的是 list(enumerate(x))
列表
它的每一个元素是由索引与值组成的 tuple
, 所以用 for index, value
来拆解。
集合的推导(comprehension)
Python 也无法在 for ... in
语句中应用 if..else
条件进行元素过滤,这就要用到推导了。Comprehension 可以同时完成集合的 filter
和 map
操作,如下
它的基本语法是
new_list = [expression for variable in old_list if expression]
new_dict = {key_expression: value_expression for variable in list if expression}
new_tuple = (expression for variable in old_tuple if expression) # 其中 old_tuple 也可以是 list
在 expression 部分加入条件
Python 中的 value1 if condition else value2
语法我比较喜欢。
Comprehension 语法同样适用于 tuple
, 例如下面的代码
对字典的推导
基于前面的推导语法,我们可以应用到 dict
上
推导中可以有多个 for
上面得到一个 a 与 b 的笛卡尔乘积
Filter/Map/Reduce 操作
现在来到本文立意的初衷,就是为了了解 Python 的 filter/map/reduce 操作。其中 filter
和 map
是可直接使用的两个函数,reduce
是来自于 functools
模块,需用 from functools import reduce
引入。看到 functools
模块名,它里边还有不少好料。
Filter
对集合的过滤接受一个返回布尔值的 Predicate 函数,或者用内联 lambda 表达式的方式
注意 filter
之后不是直接返回的 list
, 而是一个 filter
类型,要用 list(y)
转换回 list
类型。
或者用内联 lambda 的方式
filter
之后返回的虽然不是一个 list
, 但是它能被用于下一轮的 filter
. 可是又不能直接 for .. in
遍历 filter
类型。
输出是
<filter object at 0x100e11160>
<filter object at 0x100e11160>
Map
有了 Filter 作铺垫之后,Map 就好理解了,只需把返回 True 或 False 的过滤函数改成转换函数。
也是需用 list(y)
再转换回 list。也可以在 map 中用 lamba 表达式
Reduce
reduce
通常才是真正执行计算的过程,前面 filter
和 map
多是准备, 整理输入数据的。由集合收缩为一个值就是 reduce
操作,当然也可以收缩为一个集合类型值。
比如说 1 加到 100 的操作就可以采用 reduce
操作,reduce 时可以从一个自定义的初始值开始,也可从集合中的第一个元素开始。
Python 的 reduce
操作默认从集合的第一个元素开始,因此对空列表是不能 reduce
的,取不到第一个元素
reduce
也可以由第三个参数来提供初始值,如
reduce
方法的原型是
reduce(...)
reduce(function, sequence[, initial]) -> value
下面两个 reduce
用法是等效的
简单的 reduce
函数写成 lambda 表达式就行了。
链接:
[…] Python 集合的遍历,推导及 filter/map/reduce 操作 中讲了对集合的 filter, map 和 reduce 操作,那还有 sort 排序呢?像 Java 一样,Python 也提供了 sort() 和 sorted() 方法。 […]