我有一个值列表,我需要根据布尔值列表中的值进行过滤:
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]
这条线有效,但看起来(对我来说)有点矫枉过正,我想知道是否有更简单的方法来实现同样的目标。
以下答案中给出的两个好建议的摘要:
1-不要像我一样命名列表filter
,因为它是一个内置函数。
2-不要像True
那样将事情与if filter[idx]==True..
进行比较,因为这是不必要的。只需使用if filter[idx]
即可。
答案 0 :(得分:142)
您正在寻找itertools.compress
:
>>> from itertools import compress
>>> list_a = [1, 2, 4, 6]
>>> fil = [True, False, True, False]
>>> list(compress(list_a, fil))
[1, 4]
>>> 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
用作变量名,它是一个内置函数。
答案 1 :(得分:33)
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数组但不是过滤器
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
答案 2 :(得分:29)
像这样:
filtered_list = [i for (i, v) in zip(list_a, filter) if v]
使用zip
是并行迭代多个序列的'pythonic'方法,无需任何索引。将itertools用于这样一个简单的案例有点矫枉过正......
在你的例子中你应该做的一件事就是将事物与True进行比较,这通常是没有必要的。您只需撰写if filter[idx]==True: ...
。
if filter[idx]: ...
答案 3 :(得分:14)
要使用numpy执行此操作,即,如果您有一个数组a
,而不是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])
答案 4 :(得分:1)
filtered_list = [list_a[i] for i in range(len(list_a)) if filter[i]]
答案 5 :(得分:0)
内置函数zip
可用于简化操作。
filtered_list = [a for a, f in zip(list_a, filter) if f]
答案 6 :(得分:-3)
使用python 3,您可以使用list_a[filter]
来获取True
值。要获取False
的值,请使用list_a[~filter]