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"]
enumeratebei 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, numpyscheint 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 whereein Tupel zurückgegeben wird(array([2, 8], dtype=int64),)
all_id_resp_addresssollte zunächst einmal np.arraynicht sein list.
listund str, ging man offensichtlich Falsezu np.where. Wenn Sie np.arraymit etw vergleichen . Sie erhalten ein Array von Booleschen Werten. Dann np.wherefindet Positionen aller TrueWerte 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)
enumerateBei großen Listen ist dies viel schneller als das Listenverständnis. Es ist auch viel langsamer als die numpyLö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.timeitmit 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_itertoolsist eine Bibliothek eines Drittanbieters > pip install more_itertools.
conda installin 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:enumerateund 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 .indicesfor 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 valuemitindices
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_indiceswerden mit Typhinweisen implementiert . In diesem Fall ist die Liste nein Bündel von ints, daher suchen wir nach value, auch definiert als int.while-loopund .index:.index, Verwendung try-exceptfür die Fehlerbehandlung , weil ein ValueErrortreten auf, wenn valuenicht 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_indeicesist 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_listist die Liste, von der Sie die Indizes erhalten möchten, und wo valuewird 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]