Scott's Blog

学则不固, 知则不惑

0%

Python 推导式探究

推导式应该是python中最受喜爱的一部分内容了,它可以让你以一种简单的形式过滤原来的数据生成一份新的数据。

推导式

数组

在数组中,推导式的用法类似这样:

[expr for val in collection if condition]

基本上和下面的for循环的意思一样:

1
2
3
4
result = []
for val in collection:
if condition:
result.append(expr)

举例:

1
2
3
4
string = ['a','as','bat','car','dove','python']
[x.upper() for x in strings if len(x) >2]

['BAT','CAR','DOVE','PYTHON']

字典

字典的推导式,类似这样,注意外面是花括号:

1
dict_comp = {key-expr:value-expr for value in collection if condition}

快速建立键值对:

1
loc_mapping = {val:index for index,val in enumerate(strings)}

假设你有一堆股票数据:

1
2
3
4
5
6
7
prices = {
'ACME': 45.23,
'AAPL': 612.78,
'IBM': 205.55,
'HPQ': 37.20,
'FB': 10.75
}

利用字典推导来过滤这些数据:

1
2
3
4
5
6
7
# 过滤出价格高于200的
p1 = {key: value for key, value in prices.items() if value > 200}

# 找出科技公司
tech_names = {'AAPL', 'IBM', 'HPQ', 'MSFT'}
p2 = {key: value for key, value in prices.items() if key in tech_names}

集合

集合的推导式和列表几乎一样,除了外面的括号不一样

1
{expr for value in collection if condition}

假设我们需要一个集合,里面包含了所有集合元素的长度,那么可以这样写:

1
2
unique_lengths = {len(x) for x in strings}

利用map函数,可以更简洁:

1
set(map(len,strings))

复合推导

假设我们有个二维数组包含了英语和西班牙语的名字:

1
2
3
4
all_data = [
['John', 'Emily', 'Michael', 'Mary', 'Steven'],
['Maria', 'Juan', 'Javier', 'Natalia', 'Pilar']
]

我们现在想要找出这两个子列表中,包含e字母的个数大于等于两个的,这样我们写一个复合推导:

1
2
result = [name for names in all_data for name in names if name.count('e') >=2 ]
result = ['Steven']

这样写也许有点难以理解,再来看一个将元组合并成数组的例子:

1
2
3
some_tuples = [(1,2,3),(4,5,6),(7,8,9)]
flattened = [x for tup in some_tuples for x in tup]
flattened #输出 [1,2,3,4,5,6,7,8,9]

在[]中的表达式的顺序,其实和我们自己写的遍历数组是一样的:

1
2
3
4
flattened = []
for tup in some_tuples:
for x in tup:
flattened.append(x)

推导式尽管很方便,但是我们有时候也要从代码可读性上去思考问题,而不是让人在语法上面很困惑你写的代码,虽然这样也是可以的:

1
2
some_tuples = [(1,2,3),(4,5,6),(7,8,9)]
[[x for x in tup] for tup in some_tuples]

参考

  • Python for data analyse - List,Set, and Dict Comprehensions