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


87

我有一段代码应该在其中创建总机。我想返回所有打开的开关的列表。这里的“开”等于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”

Answers:


115

使用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

嗯,我知道了,我看到了一些类似的问题告诉我使用枚举,但是我想我使用的是错误的。我将列表设置为x,然后做,enumerate(x)但是我想我所做的只是枚举4?那是怎么回事吗?感谢您的帮助
查尔斯·史密斯

当您进行i for i, x列表理解时还会发生什么?我只习惯查看i for i例如或类似格式的文件,它的功能是x什么?谢谢
Charles Smith

1
@Amonenumerate在循环期间返回一个元组(ind,值),现在我们可以使用以下命令将元组的项目分配给两个变量i, x = (ind, value)。这正是该循环中发生的事情。
Ashwini Chaudhary 2014年

哦,我知道现在发生了什么。非常感谢您的帮助!
查尔斯·史密斯

对于使用Python3的任何人,在itertools.compress解决方案中,将更xrange改为range。(在Python 3中xrange重命名为range。)
MehmedB

64

如果您有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])

8
请注意,这将返回一个元组,该元组需要np.where(states)[0]实际使用结果
Rufus

17

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

请参阅下面的详细比较,在那里可以看到np.where性能优于itertools.compresslist 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)

2

您可以使用过滤器:

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))))


1

使用字典理解方式,

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}

3
这是字典理解而不是列表理解。
2014年

1

使用逐元素乘法和一组:

>>> 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}


1

只需执行以下操作:

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

感谢您的贡献,并欢迎您使用StackOverflow。但是,请阅读“编辑帮助”以改进格式,并在代码中添加一些说明。谢谢!
威尔
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.