|
楼主 |
发表于 2015-6-13 22:23:56
|
显示全部楼层
[python cookbook]
问题:你有一个数据序列,想利用一些规则从中提取出需要的值或者是缩短序列
解决:使用列表推导生成器表达式
先看看列表推导:>>> mylist = [1, 4, -5, 10, -7, 2, 3, -1]
>>> [n for n in mylist if n > 0]
[1, 4, 10, 2, 3]
>>> [n for n in mylist if n < 0]
[-5, -7, -1]
PS:相信稍微学习了一些python的鱼油对于列表推导都不陌生,这是很有python特色的一个工具,但是有一个问题,当列表很大时,我们使用列表推导会占用大量的内存,这个时候如果能有生成式就好,生成式每次用到下一个对象时即时计算而不提前计算好放在内存中,看下面的例子>>> pos = (n for n in mylist if n > 0)
>>> pos
<generator object <genexpr> at 0x1006a0eb0>
PS:可以看到这里的pos是一个生成式,原来直接把方括号变成圆括号就可以得到生成式,这也是我看这节所学到的
另外,当遇到更复杂的情况时,你需要使用filter函数values = ['1', '2', '-3', '-', '4', 'N/A', '5']
def is_int(val):
try:
x = int(val)
return True
except ValueError:
return False
ivals = list(filter(is_int, values))
print(ivals)
输出是这样的>>>
['1', '2', '-3', '4', '5']
另外 一个需要注意的是itertools模块中的compress函数(PS:吐槽一下,itertools里面的东西还真是好用啊),它以一个 iterable 对象和一个相对应的Boolean选择器序列作为输入参数。 然后输出 iterable 对象中对应选择器为True的元素。 当你需要用另外一个相关联的序列来过滤某个序列的时候,这个函数是非常有用的。比如下面的例子中想将那些对应count值大于5的地址全部输出addresses = [
'5412 N CLARK',
'5148 N CLARK',
'5800 E 58TH',
'2122 N CLARK'
'5645 N RAVENSWOOD',
'1060 W ADDISON',
'4801 N BROADWAY',
'1039 W GRANVILLE',
]
counts = [ 0, 3, 10, 4, 1, 7, 6, 1]
我们这样做>>> from itertools import compress
>>> more5 = [n > 5 for n in counts]
>>> more5
[False, False, True, False, False, True, True, False]
>>> list(compress(addresses, more5))
['5800 E 58TH', '4801 N BROADWAY', '1039 W GRANVILLE']
>>>
其实用filter函数重新定义一个函数也可以做到,不过这样做似乎更直观一些(PS:compress是压缩的意思,函数名起的真好啊)最后,列表推导还有这样的用法
>>> clip_neg = [n if n > 0 else 0 for n in mylist]
>>> clip_neg
[1, 4, 0, 10, 0, 2, 3, 0]
>>> clip_pos = [n if n < 0 else 0 for n in mylist]
>>> clip_pos
[0, 0, -5, 0, -7, 0, 0, -1]
>>>
这其实是列表推导 和条件赋值组合使用的结果,条件赋值比如:>>> a = 10
>>> b = 1 if a < 5 else 2
>>> print(b)
2
>>> a = 3
>>> c = 1 if a < 5 else 2
>>> c
1
上面的例子根据a的大小是否小于5来决定b和c的赋值~~
|
|