# Getting indices of True values in a boolean list

## Question:

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`. 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):

``````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”

## Answers:

Use `enumerate`, `list.index` returns the index of first match found.

``````>>> 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`:

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

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.

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

If you have numpy available:

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

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

Simply do this:

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

TL; DR: use `np.where` as it is the fastest option. Your options are `np.where`, `itertools.compress`, and `list comprehension`.

See the detailed comparison below, where it can be seen `np.where` outperforms both `itertools.compress` and also `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
``````
• Method 1: Using `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`
``````>>> %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`
``````>>> %timeit np.where(t)
179 µs ± 593 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
``````

I got different benchmark result compared to @meysham answer. In this test, compress seems the fastest (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`

``````>>> 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])
``````
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.