在布尔列表中获取 True 值的索引

我有一段代码,我应该创建一个交换机。我想返回所有开关的列表。这里的“开”等于 True,“关”等于 False。现在我只想返回所有 True值及其位置的列表。这是我所有的,但它只返回 True第一次出现的位置(这只是我的代码的一部分) :

self.states = [False, False, False, False, True, True, False, True, False, False, False, False, False, False, False, False]


def which_switch(self):
x = [self.states.index(i) for i in self.states if i == True]

这里只返回“4”

251492 次浏览

使用 enumeratelist.index返回找到的第一个匹配项的索引。

>>> t = [False, False, False, False, True, True, False, True, False, False, False, False, False, False, False, False]
>>> [i for i, x in enumerate(t) if x]
[4, 5, 7]

对于大型列表,最好使用 itertools.compress:

>>> from itertools import compress
>>> list(compress(xrange(len(t)), t))
[4, 5, 7]
>>> t = t*1000
>>> %timeit [i for i, x in enumerate(t) if x]
100 loops, best of 3: 2.55 ms per loop
>>> %timeit list(compress(xrange(len(t)), t))
1000 loops, best of 3: 696 µs per loop

你可以使用过滤器:

filter(lambda x: self.states[x], range(len(self.states)))

这里的 range枚举了列表中的元素,因为我们只想要那些 self.statesTrue的元素,所以我们基于这个条件应用了一个过滤器。

对于 Python > 3.0:

list(filter(lambda x: self.states[x], range(len(self.states))))


用词典理解的方式,

x = {k:v for k,v in enumerate(states) if v == True}

输入:

states = [False, False, False, False, True, True, False, True, False, False, False, False, False, False, False, False]

产出:

{4: True, 5: True, 7: True}

如果你有数字可用:

>>> import numpy as np
>>> states = [False, False, False, False, True, True, False, True, False, False, False, False, False, False, False, False]
>>> np.where(states)[0]
array([4, 5, 7])

使用元素乘法和集合:

>>> states = [False, False, False, False, True, True, False, True, False, False, False, False, False, False, False, False]
>>> set(multiply(states,range(1,len(states)+1))-1).difference({-1})

产出: {4, 5, 7}

只要这样做:

def which_index(self):
return [
i for i in range(len(self.states))
if self.states[i] == True
]

DR : 使用 np.where,因为它是最快的选项。您的选项是 np.whereitertools.compresslist comprehension

请参阅下面的详细比较,其中可以看到 ABC0的性能优于 ABC1和 list comprehension

>>> from itertools import compress
>>> import numpy as np
>>> t = [False, False, False, False, True, True, False, True, False, False, False, False, False, False, False, False]`
>>> t = 1000*t
  • 方法1: 使用 list comprehension
>>> %timeit [i for i, x in enumerate(t) if x]
457 µs ± 1.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
  • 方法2: 使用 itertools.compress
>>> %timeit list(compress(range(len(t)), t))
210 µs ± 704 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)
  • 方法3(最快的方法) : 使用 numpy.where
>>> %timeit np.where(t)
179 µs ± 593 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

我得到了与 @ meysham 回答不同的基准测试结果。在这个测试中,压缩似乎是最快的(python3.7)。

from itertools import compress
import numpy as np
t = [True, False, False, False, False, True, True, False, True, False, False, False, False, False, False, False, False]


%timeit [i for i, x in enumerate(t) if x]
%timeit list(compress(range(len(t)), t))
%timeit list(filter(lambda x: t[x], range(len(t))))
%timeit np.where(t)[0]


# 2.54 µs ± 400 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
# 2.67 µs ± 600 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
# 6.22 µs ± 624 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
# 6.52 µs ± 768 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
t = 1000*t
%timeit [i for i, x in enumerate(t) if x]
%timeit list(compress(range(len(t)), t))
%timeit list(filter(lambda x: t[x], range(len(t))))
%timeit np.where(t)[0]


# 1.68 ms ± 112 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
# 947 µs ± 105 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
# 3.96 ms ± 97 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
# 2.14 ms ± 45.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

可以使用带方括号的布尔掩码数组进行过滤,比 np.where

>>> states = [True, False, False, True]
>>> np.arange(len(states))[states]
array([0, 3])
>>> size = 1_000_000
>>> states = np.arange(size) % 2 == 0
>>> states
array([ True, False,  True, ..., False,  True, False])
>>> true_index = np.arange(size)[states]
>>> len(true_index)
500000
>>> true_index
array([     0,      2,      4, ..., 999994, 999996, 999998])