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

Cha*_*ith 63 python list

我有一段我的代码,我应该创建一个交换机.我想返回所有开关的列表.这里"开"将等于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]
Run Code Online (Sandbox Code Playgroud)

这只返回"4"

Ash*_*ary 86

使用enumerate,list.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]
Run Code Online (Sandbox Code Playgroud)

对于大型列表,最好使用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
Run Code Online (Sandbox Code Playgroud)

  • @Amon `enumerate` 在循环期间返回一个元组(ind, value),现在我们可以使用:`i, x = (ind, value)` 将元组的项目分配给两个变量。这正是该循环中发生的情况。 (2认同)
  • 对于使用 Python3 的任何人,在“itertools.compress”解决方案中,将“xrange”更改为“range”。(“xrange”在 Python 3 中被重命名为“range”。) (2认同)

jte*_*ace 50

如果您有可用的numpy:

>>> 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])
Run Code Online (Sandbox Code Playgroud)

  • 注意,这会返回一个元组,它需要`np.where(states)[0]`来实际使用结果 (7认同)

Mey*_*ghi 5

一种更有效的方法是使用np.where。请参阅下面的详细比较,在那里可以看到np.where性能优于itertools.compresslist comprehension

下面,我将接受的答案(@Ashwini Chaudhary)提出的解决方案与using进行了比较numpy.where。还要注意,在Python 3中,不推荐使用xrange(),即从python 3.x中删除了xrange()。

>>> 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
Run Code Online (Sandbox Code Playgroud)
  • 方法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)
Run Code Online (Sandbox Code Playgroud)
  • 方法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)
Run Code Online (Sandbox Code Playgroud)
  • 方法3(最快的方法):使用 numpy.where
>>> %timeit np.where(t)
179 µs ± 593 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
Run Code Online (Sandbox Code Playgroud)