Python 集合的遍历,推导及 filter/map/reduce 操作

栏目: 服务器 · 发布时间: 5年前

内容简介:借鉴于其他多数语言中集合的 map/reduce 操作,也想总结一下在 Python 中如何对集合进行 map/reduce。而不是对于 Python 集合只会用简单的因此本文将涉及到三个方面的知识,基本的集合遍历操作,集合的推导,与 filter/map/reduce 操作。我无法写出诸如 掌握 Python 集体看这一篇就够了 的文章,但基本由本篇出发能了解到 Python 集合的基本遍历,转换操作。其余如切片,和更多能作用于 Python 集合的函数未有提及, 请查阅相关文档。这一块主要是复习功课, 

借鉴于其他多数语言中集合的 map/reduce 操作,也想总结一下在 Python 中如何对集合进行 map/reduce。而不是对于 Python 集合只会用简单的 for ... in 遍历,处于之间的是 Python 的  Comprehension 操作,更倾向于译作推导; 在 Scala 中也有类似的  for-comprehension 语法。

因此本文将涉及到三个方面的知识,基本的集合遍历操作,集合的推导,与 filter/map/reduce 操作。我无法写出诸如 掌握 Python 集体看这一篇就够了 的文章,但基本由本篇出发能了解到 Python 集合的基本遍历,转换操作。其余如切片,和更多能作用于 Python 集合的函数未有提及, 请查阅相关文档。

集合的基本遍历操作

这一块主要是复习功课, 希望由此熟练掌握常用的集合遍历操作方式

基本遍历

for a in [1, 2, 3]:
    print(a)

这个 for ... in 语法可应用于 list , tuple , 和 set , 还有  range , map 等。

不过上面的语法应用于 dict 只是对 key 进行遍历

x = {"a": 1, "b": 2}
for key in x:     # 这里相当于是 for key in dict.keys():
    print(key, "=>", x['key'])

对于 dict 既然可以对 keys() 进行遍历,也就可以对值 values() 进行遍历

x = {"a": 1, "b": 2}
for value in x.values():
    print(value)       # 依次输出 1, 2

x.keys() 的类型是 dict_keyslist(x.keys() 可以得到所有 key 组成的 listset(x.keys() 得到相应的 set

x.values() 的类型是 dict_values 。也可以用 list(x.values()set(x.values() 转换为相应的 listset

dict 同时遍历 key, value

map = {"a": 1, "b": 2}
for key, value in map.items():
    print(key, "=>", value)

map.items() 类型是 dict_items , 看下方

>>> map.items()
dict_items([('a', 1), ('b', 2)])
>>> list(map.items())
[('a', 1), ('b', 2)]
>>> set(map.items())
{('b', 2), ('a', 1)}

因为每个元素是由 (key, value) 组成的 tuple , 所以能用 for key, value 进行拆解(unpack)。

遍历时得到索引

这时候要用到 enumerate 函数

x = [1, 5, 3]
for index, value in enumerate(x):
    print(index, "=>", value)

可以想像它实质遍历的是 list(enumerate(x)) 列表

>>> list(enumerate(x))
[(0, 1), (1, 5), (2, 3)]

它的每一个元素是由索引与值组成的 tuple , 所以用 for index, value 来拆解。

集合的推导(comprehension)

Python 也无法在 for ... in 语句中应用 if..else 条件进行元素过滤,这就要用到推导了。Comprehension 可以同时完成集合的 filtermap 操作,如下

x = [1, 5, 3]
y = [val * 2 for val in x]   # x 中每个元素乘以 2 得到新的列表 [2, 10, 6]
z = [val * 2 for val in x if val > 2]  # x 中大于 2 的元素诚以 2 得到新的列表 [10, 6]

它的基本语法是

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 部分加入条件

x = [1, 2, 3, 4]
>>> x = [1, 2, 3, 4]
>>> y = [True if val % 2 == 0 else False for val in x]
>>> y
[False, True, False, True]

Python 中的 value1 if condition else value2 语法我比较喜欢。

Comprehension 语法同样适用于 tuple , 例如下面的代码

>>> a = (1, 3, 5)
>>> b = (val + 2 for val in a)
>>> list(b)
[3, 5, 7]

对字典的推导

基于前面的推导语法,我们可以应用到 dict

>>> x = {"a": 1, "b": 5, "c": 3}
>>> y = {key: value + 2 for key, value in x.items()}
>>> y
{'a': 3, 'b': 7, 'c': 5}
>>> z = {key + "0": value + 2 for key, value in x.items() if value > 2}
>>> z
{'b0': 7, 'c0': 5}

推导中可以有多个 for

>>> a = [1, 3, 5]
>>> b = [2, 4, 6]
>>> x = [v1 * v2 for v1 in a for v2 in b]
>>> x
[2, 4, 6, 6, 12, 18, 10, 20, 30]

上面得到一个 a 与 b 的笛卡尔乘积

Filter/Map/Reduce 操作

现在来到本文立意的初衷,就是为了了解 Python 的 filter/map/reduce 操作。其中 filtermap 是可直接使用的两个函数, reduce 是来自于 functools 模块,需用 from functools import reduce 引入。看到 functools 模块名,它里边还有不少好料。

Filter

对集合的过滤接受一个返回布尔值的 Predicate 函数,或者用内联 lambda 表达式的方式

>>> x = [1, 3, 2, 5]
>>> def greater_then_2(val):
    return val > 2
 
>>> y = filter(greater_then_2, x)
>>> y
<filter object at 0x1071f8048>
>>> list(y)
[3, 5]

注意 filter 之后不是直接返回的 list , 而是一个 filter 类型,要用 list(y) 转换回 list 类型。

或者用内联 lambda 的方式

>>> x = [1, 3, 2, 5]
>>> y = filter(lambda a: a > 2, x)
>>> list(y)
[3, 5]
>>> z = filter(lambda a: a > 2, filter(lambda a: a > 2, x))
>>> list(z)
[3, 5]

filter 之后返回的虽然不是一个 list , 但是它能被用于下一轮的 filter . 可是又不能直接 for .. in 遍历 filter 类型。

for val in y:
    print(y)

输出是

<filter object at 0x100e11160>  <filter object at 0x100e11160>

Map

有了 Filter 作铺垫之后,Map 就好理解了,只需把返回 True 或 False 的过滤函数改成转换函数。

>>> x = [1, 3, 2, 5]
>>> def plus_1(val):
    return val + 1
 
>>> y = map(plus_1, x)
>>> y
<map object at 0x1074b9160>
>>> list(y)
[2, 4, 3, 6]

也是需用 list(y) 再转换回 list。也可以在 map 中用 lamba 表达式

y = map(lambda a: a + 1, x)

Reduce

reduce 通常才是真正执行计算的过程,前面 filtermap 多是准备, 整理输入数据的。由集合收缩为一个值就是 reduce 操作,当然也可以收缩为一个集合类型值。

比如说 1 加到 100 的操作就可以采用 reduce 操作,reduce 时可以从一个自定义的初始值开始,也可从集合中的第一个元素开始。

>>> from functools import reduce
>>> numbers = range(1, 101)  # 下面直接对 range 进行 reduce 操作
>>> def add(m, x):     # m 代表每次累加后的结果,x 是当前遍历到的元素
    return m + x
 
>>> 
>>> y = reduce(add, numbers)
>>> y
5050

Python 的 reduce 操作默认从集合的第一个元素开始,因此对空列表是不能 reduce 的,取不到第一个元素

>>> y = reduce(add, [])
Traceback (most recent call last):
  File "<pyshell#48>", line 1, in <module>
    y = reduce(add, [])
TypeError: reduce() of empty sequence with no initial value

reduce 也可以由第三个参数来提供初始值,如

>>> y = reduce(add, [], 100)
>>> y
100

reduce 方法的原型是

reduce(...)  reduce(function, sequence[, initial]) -> value

下面两个 reduce 用法是等效的

reduce(function, sequence)
reduce(function, sequence[1:], sequence[0]

简单的 reduce 函数写成 lambda 表达式就行了。

链接:

  1. Map, Filter and Reduce
  2. Comprehensions

以上所述就是小编给大家介绍的《Python 集合的遍历,推导及 filter/map/reduce 操作》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

网络素养

网络素养

[美]霍华德·莱茵戈德 / 张子凌、老卡 / 译言·东西文库/电子工业出版社 / 2013-8-1 / 49.80元

有人说Google让我们变得更笨,有人说Facebook出卖了我们的隐私,有人说Twitter将我们的注意力碎片化。在你担忧这些社会化媒体让我们变得“浅薄”的时候,有没问过自己,是否真正地掌握了使用社会化媒体的方式? 这本书将介绍五种正在改变我 们这个世界的素养:注意力、 对垃圾信息的识别能力、参与力、协作力和联网智慧。当有足够多的人学会并且能够熟练的使用这些技术,成为真正的数字公民后。健康......一起来看看 《网络素养》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

随机密码生成器
随机密码生成器

多种字符组合密码

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具