Отримання індексів True значень у логічному списку


87

У мене є частина мого коду, де я повинен створити комутатор. Я хочу повернути список усіх увімкнених комутаторів. Тут "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"

Відповіді:


115

Use 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

Ах, я бачу, я бачив кілька подібних запитань, які підказували мені використовувати перелічення, але, мабуть, я використовував це неправильно. Я встановлював список рівним x, потім робив, enumerate(x)але, мабуть, все, що я робив, було перелічення 4? Це те, що відбувалося? Дякуємо за допомогу
Чарльз Сміт

Також що відбувається, коли ви робите i for i, xв розумінні списку? Я звик бачити i for iлише, наприклад, або подібний формат, в чому функція x? Дякую
Чарльз Сміт

1
@Amon enumerateповертає набір кортежів (IND, значення) в протягом циклу, тепер ми можемо призначити пункти кортежу двох змінних з допомогою: i, x = (ind, value). Це саме те, що відбувається в цьому циклі.
Ashwini Chaudhary

О, я бачу, що зараз відбувається. Щиро дякую за допомогу!
Чарльз Сміт

Для тих, хто використовує Python3, у itertools.compressрішенні змініть xrangeна range. ( xrangeбуло перейменовано на rangePython 3.)
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]фактичного використання результатів
Руфус,

17

TL; ДР : використовуйте, np.whereоскільки це найшвидший варіант. Ваші варіанти np.where, itertools.compressі list comprehension.

Дивіться детальне порівняння нижче, де можна побачити, що воно np.whereперевершує і те, itertools.compressі інше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
  • Спосіб 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.statesце True, ми застосовуємо фільтр , заснований на цю умову.

Для 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
Це розуміння дикту, а не перелік розумінь.
Ashwini Chaudhary

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. Однак, будь ласка, прочитайте Довідку щодо редагування, щоб покращити форматування, а також додайте пояснення до свого коду. Дякую!
Буде
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.