Подтвердить что ты не робот

Получение индексов True значений в булевом списке

У меня есть часть моего кода, где я должен создать коммутатор. Я хочу вернуть список всех включенных переключателей. Здесь "on" будет равно True и "off" равно 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"

4b9b3361

Ответ 1

Использовать 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]

Для огромных списков было бы лучше использовать 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

Ответ 2

Если у вас имеется 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])

Ответ 3

Гораздо более эффективный способ - использовать np.where. См. подробное сравнение ниже, где видно, что np.where превосходит как itertools.compress, так и list comprehension.

Ниже я сравнил решения, предложенные в принятом ответе (@Ashwini Chaudhary) с использованием numpy.where. Также обратите внимание, что в Python 3 xrange() устарела, то есть xrange() удалена из python 3.x.

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

Ответ 4

Вы можете использовать фильтр для этого:

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

range здесь перечисляет элементы вашего списка, и поскольку нам нужны только те, где self.states имеет значение True, мы применяем фильтр на основе этого условия.

Для Python> 3.0:

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

Ответ 5

Просто сделайте это:

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

Ответ 6

Используйте способ понимания словаря,

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]

Вывод:

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

Ответ 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}