列表中有一些数据,我们想提取或删除某些值,该怎么办?
解决方案
最简单的方法是使用列表推导式(list comprehension)。例如:
代码语言:javascript复制>>> 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]
>>>
列表推导式的使用需要注意其内存占用,当原始列表比较大时,其内存占用较高,可以使用生成器表达式通过迭代的方式产生筛选结果:
代码语言:javascript复制>>> pos = (n for n in mylist if n > 0)
>>> pos
<generator object <genexpr> at 0x1006a0eb0>
>>> for x in pos:
... print(x)
...
1
4
10
2
3
>>>
有时候筛选标准较为复杂,无法在列表推导式或生成器表达式中表示。比如,假设筛选过程涉及异常处理或其他一些复杂的操作。这时,可以将筛选逻辑放到单独的函数中,使用内建的 filter() 函数处理。
代码语言:javascript复制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)
# Outputs ['1', '2', '-3', '4', '5']
因为 filter() 函数创建的是一个迭代器,因此如果后续需要一个列表的话,需要使用 list() 进行转换。
讨论
列表推导式和生成器表达式是筛选数据最简单的方式,其实,还可以在列表推导式中对数据做更复杂的操作,例如:
代码语言:javascript复制>>> mylist = [1, 4, -5, 10, -7, 2, 3, -1]
>>> import math
>>> [math.sqrt(n) for n in mylist if n > 0]
[1.0, 2.0, 3.1622776601683795, 1.4142135623730951, 1.7320508075688772]
>>>
筛选操作的另一变种形式是替换不满足条件的值,而不是丢弃它们。例如:
代码语言:javascript复制>>> 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]
>>>
另一个值得一提的筛选工具是 itertools.compress(),它可以接受一个可迭代对象和一个布尔选择器序列作为输入。输出时,它会给出所有在相应的布尔选择器中为 True 的可迭代对象元素。例如:
代码语言:javascript复制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]
现在我们想将那些对应的 count 值大于5的地址全部输出,可以尝试以下方法:
代码语言:javascript复制>>> 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', '1060 W ADDISON', '4801 N BROADWAY']
>>>
这里的关键是先构建一个布尔序列,用来表示哪些元素满足我们的条件。然后 compress() 函数挑选出满足布尔值为 True 的相应元素。
和 filter() 函数类似,compress() 也返回一个迭代器。因此,如果需要的话,需要使用 list() 将结果转换为列表。
参考
- 《Python Cookbook》第三版
- http://python3-cookbook.readthedocs.org/zh_CN/latest/