问题描述
在vanilla Python 3 中是否有一种惯用的方法来屏蔽数组的元素?例如:
a = [True,False,True,False]
b = [2,3,5,7]
b[a]
我希望 b[a]
会返回 [2,5]
,但出现错误:
类型错误:列表索引必须是整数或切片,而不是列表
在 R 中,这按我的预期工作(使用 c()
而不是 []
来创建列表)。我知道 NumPy 有 MaskedArray
可以做到这一点,我正在寻找一种在普通 Python 中做到这一点的惯用方法。当然,我可以使用循环并遍历掩码列表和元素列表,但我希望有一种更有效的方法来使用更高级别的抽象来掩码元素。
解决方法
您可以使用itertools.compress
:
>>> from itertools import compress
>>> a = [True,False,True,False]
>>> b = [2,3,5,7]
>>> list(compress(b,a))
[2,5]
请参阅"itertools.compress()" document了解更多详情
,我认为没有很多方法可以做到这一点,您可以使用 zip
:
print([y for x,y in zip(a,b) if x])
输出:
[2,5]
您也可以为此创建一个带有 class
的 __getitem__
:
class index:
def __init__(self,seq):
self.seq = seq
def __getitem__(self,boolseq):
return [x for x,y in zip(boolseq,self.seq) if y]
print(index(a)[b])
输出:
[2,5]
,
你可以使用列表理解:
[b[i] for i in range(len(a)) if a[i]]
或
[b[i] for i,mask in enumerate(a) if maks]
在这两种情况下,通过迭代每个元素并仅在掩码为 true
时才插入它来创建列表。
你可以使用一个 pandas.Series
,它允许像 dataframe 一样,用一个布尔数组过滤数据
from pandas import Series
a = [True,False]
b = [2,7]
res = Series(b)[a].tolist()
print(res) # [2,5]
,
在众多选项中,您可以:
1.使用迭代工具 compress
from itertools import compress
a = [True,7]
result_itertools = list(compress(b,a))
print(result_itertools)
2.使用 Filter Function
result_filter = list(filter(lambda x: x[0],zip(a,b)))
for item in result_filter:
print(item[1])
# 2
# 5
3.使用 List Comprehension
result_comprehension = [value for bool_,value in zip(a,b) if bool_]
print(result_comprehension)
# [2,5]