ブールリストでTrue値のインデックスを取得する


88

配電盤を作成することになっているコードの一部があります。オンになっているすべてのスイッチのリストを返したいのですが。ここで、「オン」は等しくTrue、「オフ」は等しくなり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」のみを返します

回答:


118

を使用して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]

巨大なリストの場合は、以下を使用することをお勧めします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を列挙することだけだったと思いますか?それは何が起こっていたのですか?助けてくれてありがとう
Amon

またi for i, x、リスト内包表記を行うとどうなりますか?i for iたとえば、または同様の形式を見るのに慣れているだけですが、その機能はx何ですか?ありがとう
Amon 2014年

1
@Amonenumerateはループ中にタプル(ind、value)を返します。これで、タプルのアイテムを次のように2つの変数に割り当てることができますi, x = (ind, value)。これはまさにそのループで起こっていることです。
アシュウィニ・チャウダリー

ああ、私は今何が起こっているのかわかります。どうもありがとうございました!
アモン

Python3を使用している場合は、itertools.compressソリューションで、をに変更xrangerangeます。(Python 3でxrange名前が変更されrangeました。)
MehmedB20年

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]により、実際に結果を使用する必要があるタプルが返されることに注意してください
Rufus

17

TL; DRnp.where最速のオプションなので使用してください。次のオプションがありnp.whereitertools.compresslist comprehension

以下の詳細な比較を参照してください。ここではnp.whereitertools.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 2014年

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へようこそ。ただし、フォーマットを改善するために編集ヘルプを読み、コードに説明を追加してください。ありがとう!
ウィル
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.