Bir boole listesindeki True değerlerinin indislerini alma


88

Santral oluşturmam gereken kodumun bir parçası var. Açık olan tüm anahtarların bir listesini döndürmek istiyorum. Burada "açık" eşit olacak Trueve "kapalı" eşit olacaktır False. Şimdi sadece tüm Truedeğerlerin ve konumlarının bir listesini döndürmek istiyorum . Sahip olduğum tek şey bu, ancak yalnızca ilk oluşumunun konumunu döndürüyor True(bu, kodumun yalnızca bir kısmı):

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]

Bu yalnızca "4" değerini döndürür

Yanıtlar:


118

Kullan enumerate, list.indexbulunan ilk eşleşmenin dizinini döndürür.

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

Büyük listeler için itertools.compressşunları kullanmak daha iyi olacaktır :

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

Ahh anladım, numaralandırmayı kullanmamı söyleyen benzer sorular gördüm, ama sanırım yanlış kullanıyorum. Listeyi eşit ayarlıyordum x, sonra yapıyordum enumerate(x)ama sanırım tek yaptığım 4? Olan bu muydu? Yardım için teşekkürler
Amon

Ayrıca i for i, x, liste kavrayışını yaptığınızda ne oluyor ? Ben sadece i for iörneğin veya benzer bir formatı görmeye alışkınım , işlevi xnedir? Teşekkürler
Amon

1
@Amon enumerateşimdi kullanarak iki değişkenlere başlığın öğeleri atayabilir döngü sırasında dizilerini (ind, değer) döndürür: i, x = (ind, value). Bu döngüde olan tam olarak budur.
Ashwini Chaudhary

Oh, şimdi ne olduğunu görüyorum. Yardımınız için çok teşekkür ederim!
Amon

Python3 kullanan herkes için, içinde itertools.compressçözelti, değiştirmek xrangeiçin range. ( Python 3'te xrangeyeniden adlandırıldı range.)
MehmedB

64

Eğer uyuşturucunuz varsa:

>>> 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
Bunun np.where(states)[0], sonuçları gerçekten kullanmayı gerektiren bir demet döndürdüğünü unutmayın
Rufus

17

TL; DR : np.whereen hızlı seçenek olarak kullanın. Seçenekleriniz şunlardır np.where, itertools.compressve list comprehension.

np.whereHem itertools.compressve hem de daha iyi performans gösterdiğininlist comprehension görülebileceği aşağıdaki ayrıntılı karşılaştırmaya bakın .

>>> 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
  • Yöntem 1: Kullanma 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)
  • Yöntem 2: Kullanma itertools.compress
>>> %timeit list(compress(range(len(t)), t))
210 µs ± 704 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)
  • Yöntem 3 (en hızlı yöntem): Kullanma numpy.where
>>> %timeit np.where(t)
179 µs ± 593 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

2

Bunun için filtre kullanabilirsiniz:

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

rangeBuraya listenin elemanlarını sıralar ve biz burada sadece bu istiyoruz çünkü self.statesedilir True, bu rahatsızlıklarda temel alan bir filtre uygulamaktadır.

Python> 3.0 için:

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


1

Sözlük anlama yolu kullanın,

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

Giriş:

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

Çıktı:

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

3
Bu bir dikt-anlama değil, liste anlama.
Ashwini Chaudhary

1

Eleman bazlı çarpma ve bir küme kullanma:

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

Çıktı: {4, 5, 7}


1

Basitçe şunu yapın:

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

Katkınız için teşekkürler ve StackOverflow'a hoş geldiniz. Ancak, biçimlendirmenizi geliştirmek için Düzenleme Yardımı'nı okuyun ve ayrıca kodunuza bazı açıklamalar ekleyin. Teşekkürler!
Will
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.