numpy 基于布尔值列表过滤列表

92vpleto  于 2023-03-02  发布在  其他
关注(0)|答案(7)|浏览(166)

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

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-不要像我对if filter[idx]==True..那样拿True做比较,因为这是不必要的,使用if filter[idx]就足够了。

d4so4syb

d4so4syb1#

您正在查找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作为变量名,它是一个内置函数。

cs7cruho

cs7cruho2#

就像这样:

filtered_list = [i for (i, v) in zip(list_a, filter) if v]

使用zip是一种 * pythonic * 方式,可以并行迭代多个序列,而不需要任何索引。这里假设两个序列具有相同的长度(zip在最短的运行结束后停止)。对于这样一个简单的情况,使用itertools有点矫枉过正...
在你的例子中,有一件事是你应该停止做的,那就是把事情和True比较,这通常是不必要的。你可以简单地写if filter[idx]: ...来代替if filter[idx]==True: ...

k10s72fa

k10s72fa3#

伴麻木:

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数组而不是filter,请参阅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
ccrfmcuu

ccrfmcuu4#

要使用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])
ff29svar

ff29svar5#

filtered_list = [list_a[i] for i in range(len(list_a)) if filter[i]]
ljo96ir5

ljo96ir56#

可能不太优雅,但我认为这个解决方案的语法更简单。我将filter重命名为filter_,以避免与内置函数冲突:

list_a = [1, 2, 4, 6]
filter_ = [True, False, True, False]

这里的解决方案:

index = [i for i in range(len(filter_)) if filter_[i]]
list_a_filtered = [list_a[i] for i in index]

或在一行中:

list_a_filtered = [list_a[i] for i in [j for j in range(len(filter_)) if filter_[j]]]
slsn1g29

slsn1g297#

在python3中,你可以使用list_a[filter]来获取True的值,使用list_a[~filter]来获取False的值

相关问题