示例:
from __future__ import division
import numpy as np
n = 8
"""masking lists"""
lst = range(n)
print lst
# the mask (filter)
msk = [(el>3) and (el<=6) for el in lst]
print msk
# use of the mask
print [lst[i] for i in xrange(len(lst)) if msk[i]]
"""masking arrays"""
ary = np.arange(n)
print ary
# the mask (filter)
msk = (ary>3)&(ary<=6)
print msk
# use of the mask
print ary[msk] # very elegant
结果是:
>>>
[0, 1, 2, 3, 4, 5, 6, 7]
[False, False, False, False, True, True, True, False]
[4, 5, 6]
[0 1 2 3 4 5 6 7]
[False False False False True True True False]
[4 5 6]
正如您所看到的,与list相比,数组上的屏蔽操作更加优雅。如果您尝试在列表中使用数组屏蔽方案,则会出现错误:
>>> lst[msk]
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
TypeError: only integer arrays with one element can be converted to an index
问题是为list
s找到优雅的屏蔽。
更新
jamylak
接受了compress
的回答,但Joel Cornett
提到的要点使解决方案完全符合我感兴趣的形式。
>>> mlist = MaskableList
>>> mlist(lst)[msk]
>>> [4, 5, 6]
答案 0 :(得分:25)
您正在寻找itertools.compress
来自文档的示例
相当于:
def compress(data, selectors):
# compress('ABCDEF', [1,0,1,0,1,1]) --> A C E F
return (d for d, s in izip(data, selectors) if s)
答案 1 :(得分:7)
由于jamylak已经用实际答案回答了问题,这里是我的内置掩码支持列表示例(完全没必要,顺便说一句):
from itertools import compress
class MaskableList(list):
def __getitem__(self, index):
try: return super(MaskableList, self).__getitem__(index)
except TypeError: return MaskableList(compress(self, index))
用法:
>>> myList = MaskableList(range(10))
>>> myList
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> mask = [0, 1, 1, 0]
>>> myList[mask]
[1, 2]
请注意,当数据或掩码用完时,compress
会停止。如果您希望保持列表中超出掩码长度的部分,您可以尝试类似:
from itertools import izip_longest
[i[0] for i in izip_longest(myList, mask[:len(myList)], fillvalue=True) if i[1]]
答案 2 :(得分:4)
如果您使用的是Numpy,则可以使用Numpy数组轻松完成,而无需安装任何其他库:
>> a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>> msk = [ True, False, False, True, True, True, True, False, False, False]
>> a = np.array(a) # convert list to numpy array
>> result = a[msk] # mask a
>> result.tolist()
[0, 3, 4, 5, 6]
答案 3 :(得分:3)
我不认为它很优雅。它结构紧凑,但往往令人困惑,因为构造与大多数语言非常不同。
正如Rossum所说的语言设计,我们花更多时间阅读它而不是写作。一行代码的构造越模糊,对其他人来说就越容易混淆,因为他们可能不熟悉Python,即使他们在任何其他语言中都具备完全的能力。
可读性在服务代码的现实世界中每天都胜过简短的表示法。就像修车一样。包含大量信息的大图使故障排除变得更加容易。
对我来说,我更倾向于对使用长格式
的代码进行故障排除print [lst[i] for i in xrange(len(lst)) if msk[i]]
比numpy短符号掩码。我不需要具备特定Python包的任何特殊知识来解释它。
答案 4 :(得分:2)
以下在 Python 3 中运行良好:
np.array(lst)[msk]
如果您需要返回列表作为结果:
np.array(lst)[msk].tolist()
答案 5 :(得分:0)
您也可以只使用列表和邮政编码
def masklist(mylist,mymask):
return [a for a,b in zip(mylist,mymask) if b]
n = 8
lst = range(n)
msk = [(el>3) and (el<=6) for el in lst]
lst_msk = masklist(lst,msk)
print(lst_msk)