根据布尔值列表过滤列表
我有一个值列表,我需要过滤布尔值列表中的值:
list_a = [1, 2, 4, 6] filter = [True, False, True, False]
我用下面一行生成一个新的过滤列表:
filtered_list = [i for indx,i in enumerate(list_a) if filter[indx] == True]
这导致:
print filtered_list [1,4]
这条线的工作,但看起来(对我来说)有点矫枉过正,我想知道是否有一个简单的方法来实现相同的。
build议
下面的答案给出了两个很好的build议总结:
1-不要像我这样命名列表filter
因为它是一个内置函数。
2-不要把事情比作True
就像我if filter[idx]==True..
因为这是不必要的。 只要使用if filter[idx]
就足够了。
您正在寻找itertools.compress
:
>>> from itertools import compress >>> list_a = [1, 2, 4, 6] >>> fil = [True, False, True, False] >>> list(compress(list_a, fil)) [1, 4]
时间比较(py3.x):
>>> list_a = [1, 2, 4, 6] >>> fil = [True, False, True, False] >>> %timeit list(compress(list_a, fil)) 100000 loops, best of 3: 2.58 us per loop >>> %timeit [i for (i, v) in zip(list_a, fil) if v] #winner 100000 loops, best of 3: 1.98 us per loop >>> list_a = [1, 2, 4, 6]*100 >>> fil = [True, False, True, False]*100 >>> %timeit list(compress(list_a, fil)) #winner 10000 loops, best of 3: 24.3 us per loop >>> %timeit [i for (i, v) in zip(list_a, fil) if v] 10000 loops, best of 3: 82 us per loop >>> list_a = [1, 2, 4, 6]*10000 >>> fil = [True, False, True, False]*10000 >>> %timeit list(compress(list_a, fil)) #winner 1000 loops, best of 3: 1.66 ms per loop >>> %timeit [i for (i, v) in zip(list_a, fil) if v] 100 loops, best of 3: 7.65 ms per loop
不要使用filter
作为variables名称,它是一个内置函数。
随着numpy:
In [128]: list_a = np.array([1, 2, 4, 6]) In [129]: filter = np.array([True, False, True, False]) In [130]: list_a[filter] Out[130]: array([1, 4])
或者看看Alex Szatmary的回答,如果list_a可以是一个numpy数组而不是filter
Numpy通常也给你一个很大的速度提升
In [133]: list_a = [1, 2, 4, 6]*10000 In [134]: fil = [True, False, True, False]*10000 In [135]: list_a_np = np.array(list_a) In [136]: fil_np = np.array(fil) In [139]: %timeit list(itertools.compress(list_a, fil)) 1000 loops, best of 3: 625 us per loop In [140]: %timeit list_a_np[fil_np] 10000 loops, best of 3: 173 us per loop
像这样:
filtered_list = [i for (i, v) in zip(list_a, filter) if v]
使用zip
是并行遍历多个序列的“pythonic”方法,不需要任何索引。 使用itertools这样一个简单的情况是有点矫枉过正…
在你的例子中你应该停止做的一件事情是将事情与真实比较,这通常是没有必要的。 而不是if filter[idx]==True: ...
,你可以简单地写过if filter[idx]: ...
要做到这一点使用numpy,即,如果你有一个数组,而不是list_a
:
a = np.array([1, 2, 4, 6]) my_filter = np.array([True, False, True, False], dtype=bool) a[my_filter] > array([1, 4])