[英]Getting indices of True values in a boolean list
我有一段代碼,我應該在其中創建一個總機。 我想返回所有打開的開關的列表。 這里“on”將等於True
,“off”等於False
。 所以現在我只想返回所有True
值及其 position 的列表。這就是我所擁有的,但它只返回第一次出現True
的 position(這只是我的代碼的一部分):
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”
使用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
如果你有 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])
TL; DR :使用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
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)
itertools.compress
>>> %timeit list(compress(range(len(t)), t))
210 µs ± 704 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)
numpy.where
>>> %timeit np.where(t)
179 µs ± 593 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
您可以使用過濾器:
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))))
使用字典理解方式,
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}
使用逐元素乘法和一個集合:
>>> 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}
只需這樣做:
def which_index(self):
return [
i for i in range(len(self.states))
if self.states[i] == True
]
與@meysham answer相比,我得到了不同的基准測試結果。 在此測試中,壓縮似乎是最快的(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)
您可以使用帶方括號的 boolean 掩碼數組進行過濾,它比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])
index_of_element=list_name.index(True)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.