问题:根据布尔值列表过滤列表
我有一个值列表,需要根据布尔值列表中的值进行过滤:
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
您正在寻找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
用作变量名,它是一个内置函数。
回答 1
像这样:
filtered_list = [i for (i, v) in zip(list_a, filter) if v]
使用zip
是在多个索引上并行迭代的pythonic方式,无需任何索引。假设两个序列的长度相同(最短用完后拉链停止)。使用itertools
这种简单的情况有点过分…
在示例中您应该真正停止做的一件事是将事物与True进行比较,这通常不是必需的。相反if filter[idx]==True: ...
,您可以简单地编写if filter[idx]: ...
。
回答 2
使用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])
或者,如果list_a可以是一个numpy数组但不能过滤,请查看Alex Szatmary的答案
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
回答 3
为此,请使用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
filtered_list = [list_a[i] for i in range(len(list_a)) if filter[i]]
回答 5
使用python 3,您可以list_a[filter]
用来获取True
值。要获得False
价值,请使用list_a[~filter]
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。