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 操作》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

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

Refactoring

Refactoring

Martin Fowler、Kent Beck、John Brant、William Opdyke、Don Roberts / Addison-Wesley Professional / 1999-7-8 / USD 64.99

Refactoring is about improving the design of existing code. It is the process of changing a software system in such a way that it does not alter the external behavior of the code, yet improves its int......一起来看看 《Refactoring》 这本书的介绍吧!

html转js在线工具
html转js在线工具

html转js在线工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具