简体   繁体   English

获取 boolean 列表中真值的索引

[英]Getting indices of True values in a boolean list

I have a piece of my code where I'm supposed to create a switchboard.我有一段代码,我应该在其中创建一个总机。 I want to return a list of all the switches that are on.我想返回所有打开的开关的列表。 Here "on" will equal True and "off" equal False .这里“on”将等于True ,“off”等于False So now I just want to return a list of all the True values and their position. This is all I have but it only return the position of the first occurrence of True (this is just a portion of my code):所以现在我只想返回所有True值及其 position 的列表。这就是我所拥有的,但它只返回第一次出现True的 position(这只是我的代码的一部分):

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]

This only returns "4"这只返回“4”

Use enumerate , list.index returns the index of first match found.使用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]

For huge lists, it'd be better to use itertools.compress :对于巨大的列表,最好使用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

If you have numpy available:如果你有 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])

TL; TL; DR : use np.where as it is the fastest option. DR :使用np.where因为它是最快的选择。 Your options are np.where , itertools.compress , and list comprehension .您的选项是np.whereitertools.compresslist comprehension

See the detailed comparison below, where it can be seen np.where outperforms both itertools.compress and also list 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
  • Method 1: Using list comprehension方法 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)
  • Method 2: Using itertools.compress方法二:使用itertools.compress
>>> %timeit list(compress(range(len(t)), t))
210 µs ± 704 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)
  • Method 3 (the fastest method): Using numpy.where方法 3(最快的方法):使用numpy.where
>>> %timeit np.where(t)
179 µs ± 593 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

You can use filter for it:您可以使用过滤器:

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

The range here enumerates elements of your list and since we want only those where self.states is True , we are applying a filter based on this condition.此处的range枚举列表中的元素,因为我们只需要self.statesTrue元素,因此我们正在根据此条件应用过滤器。

For Python > 3.0:对于 Python > 3.0:

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

Use dictionary comprehension way,使用字典理解方式,

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

Input:输入:

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

Output:输出:

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

Using element-wise multiplication and a set:使用逐元素乘法和一个集合:

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

Output: {4, 5, 7}输出: {4, 5, 7}

Simply do this:只需这样做:

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

I got different benchmark result compared to @meysham answer .@meysham answer相比,我得到了不同的基准测试结果。 In this test, compress seems the fastest (python 3.7).在此测试中,压缩似乎是最快的(python 3.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)

You can filter by using boolean mask array with square bracket, it's faster than np.where您可以使用带方括号的 boolean 掩码数组进行过滤,它比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])
index_of_element=list_name.index(True)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM