根据布尔值列表过滤列表

我有一个值列表,我需要过滤布尔值列表中的值:

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])