index()
gibt nur das erste Vorkommen eines Elements in einer Liste an. Gibt es einen netten Trick, der alle Indizes in einer Liste zurückgibt?
index()
gibt nur das erste Vorkommen eines Elements in einer Liste an. Gibt es einen netten Trick, der alle Indizes in einer Liste zurückgibt?
Antworten:
Sie können ein Listenverständnis verwenden:
indices = [i for i, x in enumerate(my_list) if x == "whatever"]
enumerate
bei 2.3. Also ja, wenn Ihr Python uralt ist, verwenden Sie filter()
.
print([i for i, x in enumerate([[1,1],[0,1]]) if x == 1])
gibt []
statt [[0, 1], [0, 0], [1, 1]]
.
(a == 1).nonzero()
ein NumPy-Array ausführen können a
.
Obwohl dies keine direkte Lösung für Listen ist, numpy
scheint es wirklich für diese Art von Dingen:
import numpy as np
values = np.array([1,2,3,1,2,4,5,6,3,2,1])
searchval = 3
ii = np.where(values == searchval)[0]
kehrt zurück:
ii ==>array([2, 8])
Dies kann für Listen (Arrays) mit einer großen Anzahl von Elementen im Vergleich zu einigen anderen Lösungen erheblich schneller sein.
[0]
wird benötigt, weil where
ein Tupel zurückgegeben wird(array([2, 8], dtype=int64),)
all_id_resp_address
sollte zunächst einmal np.array
nicht sein list
.
list
und str
, ging man offensichtlich False
zu np.where
. Wenn Sie np.array
mit etw vergleichen . Sie erhalten ein Array von Booleschen Werten. Dann np.where
findet Positionen aller True
Werte des Arrays.
Eine Lösung mit list.index
:
def indices(lst, element):
result = []
offset = -1
while True:
try:
offset = lst.index(element, offset+1)
except ValueError:
return result
result.append(offset)
enumerate
Bei großen Listen ist dies viel schneller als das Listenverständnis. Es ist auch viel langsamer als die numpy
Lösung, wenn Sie das Array bereits haben, da sonst die Kosten für die Konvertierung den Geschwindigkeitsgewinn überwiegen (getestet auf ganzzahligen Listen mit 100, 1000 und 10000 Elementen).
HINWEIS: Ein Hinweis zur Vorsicht basierend auf dem Kommentar von Chris_Rands: Diese Lösung ist schneller als das Listenverständnis, wenn die Ergebnisse ausreichend spärlich sind, die Liste jedoch viele Instanzen des durchsuchten Elements enthält (mehr als ~ 15% der Liste) Bei einem Test mit einer Liste von 1000 Ganzzahlen ist das Listenverständnis schneller.
timeit.timeit
mit zufällig generierten Listen verwendet habe. Das ist jedoch ein wichtiger Punkt, und ich nehme an, das ist vielleicht der Grund, warum Sie fragen. Zu der Zeit ist es mir nicht in den Sinn gekommen, aber die Geschwindigkeitsgewinne sind nur wahr, wenn die Ergebnisse ausreichend spärlich sind. Ich habe gerade mit einer Liste getestet, die das zu suchende Element enthält, und sie ist viel langsamer als das Listenverständnis.
more_itertools.locate
findet Indizes für alle Elemente, die eine Bedingung erfüllen.
from more_itertools import locate
list(locate([0, 1, 1, 0, 1, 0, 0]))
# [1, 2, 4]
list(locate(['a', 'b', 'c', 'b'], lambda x: x == 'b'))
# [1, 3]
more_itertools
ist eine Bibliothek eines Drittanbieters > pip install more_itertools
.
conda install
in letzter Zeit sehr instabil geworden ist)
Eine weitere Lösung (Entschuldigung, wenn Duplikate) für alle Vorkommen:
values = [1,2,3,1,2,4,5,6,3,2,1]
map(lambda val: (val, [i for i in xrange(len(values)) if values[i] == val]), values)
Oder verwenden Sie range
(Python 3):
l=[i for i in range(len(lst)) if lst[i]=='something...']
Für (Python 2):
l=[i for i in xrange(len(lst)) if lst[i]=='something...']
Und dann (beide Fälle):
print(l)
Ist wie erwartet.
Verwenden von filter () in python2.
>>> q = ['Yeehaw', 'Yeehaw', 'Googol', 'B9', 'Googol', 'NSM', 'B9', 'NSM', 'Dont Ask', 'Googol']
>>> filter(lambda i: q[i]=="Googol", range(len(q)))
[2, 4, 9]
Sie können ein Standarddiktat erstellen
from collections import defaultdict
d1 = defaultdict(int) # defaults to 0 values for keys
unq = set(lst1) # lst1 = [1, 2, 2, 3, 4, 1, 2, 7]
for each in unq:
d1[each] = lst1.count(each)
else:
print(d1)
Mit enumerate (alist) können Sie das erste Element (n) speichern, das der Index der Liste ist, wenn das Element x dem entspricht, wonach Sie suchen.
>>> alist = ['foo', 'spam', 'egg', 'foo']
>>> foo_indexes = [n for n,x in enumerate(alist) if x=='foo']
>>> foo_indexes
[0, 3]
>>>
Diese Funktion verwendet das Element und die Liste als Argumente und gibt die Position des Elements in der Liste zurück, wie wir zuvor gesehen haben.
def indexlist(item2find, list_or_string):
"Returns all indexes of an item in a list or a string"
return [n for n,item in enumerate(list_or_string) if item==item2find]
print(indexlist("1", "010101010"))
Ausgabe
[1, 3, 5, 7]
for n, i in enumerate([1, 2, 3, 4, 1]):
if i == 1:
print(n)
Ausgabe:
0
4
for-loop
:enumerate
und ein Listenverständnis sind effizienter und pythonischer. Diese Antwort richtet sich jedoch an Schüler, denen es möglicherweise nicht gestattet ist, einige dieser integrierten Funktionen zu verwenden .indices
for i in range(len(x)):
, die im Wesentlichen eine Liste von Indexpositionen durchläuft[0, 1, 2, 3, ..., len(x)-1]
i
, wo x[i]
eine Übereinstimmung value
mitindices
def get_indices(x: list, value: int) -> list:
indices = list()
for i in range(len(x)):
if x[i] == value:
indices.append(i)
return indices
n = [1, 2, 3, -50, -60, 0, 6, 9, -60, -60]
print(get_indices(n, -60))
>>> [4, 8, 9]
get_indices
werden mit Typhinweisen implementiert . In diesem Fall ist die Liste n
ein Bündel von int
s, daher suchen wir nach value
, auch definiert als int
.while-loop
und .index
:.index
, Verwendung try-except
für die Fehlerbehandlung , weil ein ValueError
treten auf, wenn value
nicht in der Liste enthalten ist.def get_indices(x: list, value: int) -> list:
indices = list()
i = 0
while True:
try:
# find an occurrence of value and update i to that index
i = x.index(value, i)
# add i to the list
indices.append(i)
# advance i by 1
i += 1
except ValueError as e:
break
return indices
print(get_indices(n, -60))
>>> [4, 8, 9]
get_indeices
ist etwas schneller (~ 15%) als das normale Listenverständnis. Ich versuche es herauszufinden.
Wenn Sie Python 2 verwenden, können Sie damit die gleiche Funktionalität erreichen:
f = lambda my_list, value:filter(lambda x: my_list[x] == value, range(len(my_list)))
Wo my_list
ist die Liste, von der Sie die Indizes erhalten möchten, und wo value
wird der Wert gesucht? Verwendungszweck:
f(some_list, some_element)
Wenn Sie nach den Positionen aller Elemente zwischen bestimmten Indizes suchen müssen , können Sie diese angeben:
[i for i,x in enumerate([1,2,3,2]) if x==2 & 2<= i <=3] # -> [3]