Wie finde ich alle Vorkommen eines Elements in einer Liste?

378

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?

Bruce
quelle
1
Diese Frage verwirrt mich ein wenig: Möchten Sie rekursiv in allen Ebenen einer mehrdimensionalen Liste nach einem Element suchen oder nur in der obersten Ebene der Liste nach Vorkommen suchen?
Anderson Green
22
Meiner Meinung nach sollte es eine Listenmethode geben, die genau dies tut.
Otocan

Antworten:

545

Sie können ein Listenverständnis verwenden:

indices = [i for i, x in enumerate(my_list) if x == "whatever"]
Sven Marnach
quelle
3
Verwenden Sie bei älteren Pythons filter () für im Wesentlichen dieselbe Funktionalität.
Gleno
44
Das Listenverständnis zeigte sich in Python bei 2.0, enumeratebei 2.3. Also ja, wenn Ihr Python uralt ist, verwenden Sie filter().
Steven Rumbalski
2
Diese Technik findet nicht alle Vorkommen eines Elements in einem mehrdimensionalen Array. Zum Beispiel print([i for i, x in enumerate([[1,1],[0,1]]) if x == 1])gibt []statt [[0, 1], [0, 0], [1, 1]].
Anderson Green
10
@AndersonGreen: Der Begriff "mehrdimensionales Array" schlägt eine Datenstruktur vor, die garantiert eine einheitliche Größe entlang jeder ihrer Achsen aufweist. Es gibt keine solche Datenstruktur in einfachem Python. Es gibt Listen von Listen, aber sie unterscheiden sich stark von "mehrdimensionalen Arrays". Wenn Sie Letzteres möchten, sollten Sie NumPy verwenden, mit dem Sie beispielsweise (a == 1).nonzero()ein NumPy-Array ausführen können a.
Sven Marnach
2
@ MadmanLee Wenn Sie etwas schnelles wollen, verwenden Sie NumPy. Siehe die Antwort von JoshAdel
Georgy
117

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.

JoshAdel
quelle
2
Ich habe festgestellt, dass die [0] am Ende ein Array in einen String konvertiert. Ich bin gespannt, warum Sie sich dafür entschieden haben.
Amelia
5
@amelia [0]wird benötigt, weil whereein Tupel zurückgegeben wird(array([2, 8], dtype=int64),)
Winand
1
Hey @ Winand, ich habe [0] eingegeben, bekomme aber trotzdem beide Teile. Hier ist mein Code: (nrg.local_logs.all_id_resp_address ist eine Liste) "ste =" 199.38.164.165 "value = np.where (nrg.local_logs.all_id_resp_address == ste) [0]" Ich werde mich freuen, wenn Sie es beurteilen können mir was ich falsch gemacht habe
Tomer
2
@Tomer all_id_resp_addresssollte zunächst einmal np.arraynicht sein list.
Winand
1
@Tomer Du versuchen , zu vergleichen 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.
Winand
29

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.

Paulo Almeida
quelle
3
Sie sagen, dies ist schneller als eine Listenkomposition. Können Sie Ihre Timings anzeigen, die dies demonstrieren?
Chris_Rands
5
Dies ist eine lange Zeit her, die ich wahrscheinlich 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.
Paulo Almeida
18

Wie wäre es mit:

In [1]: l=[1,2,3,4,3,2,5,6,7]

In [2]: [i for i,val in enumerate(l) if val==3]
Out[2]: [2, 4]
NPE
quelle
10
occurrences = lambda s, lst: (i for i,e in enumerate(lst) if e == s)
list(occurrences(1, [1,2,3,1])) # = [0, 3]
Phihag
quelle
8

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.

Pylang
quelle
1
könnte schön sein, wenn diese lib zu conda-forge hinzugefügt wurde (obwohl sie conda installin letzter Zeit sehr instabil geworden ist)
matanster
4

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)
Artsiom Rudzenka
quelle
4

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.

U10-Vorwärts
quelle
4

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]
Niranjan Nagaraju
quelle
2

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)
privatevoid
quelle
2

Abrufen aller Vorkommen und der Position eines oder mehrerer (identischer) Elemente in einer Liste

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

Lassen Sie uns unsere Funktion findindex machen

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]

Einfach

for n, i in enumerate([1, 2, 3, 4, 1]):
    if i == 1:
        print(n)

Ausgabe:

0
4
Giovanni G. PY
quelle
Diese Antwort war für mich am einfachsten in meinen vorhandenen Code zu implementieren.
Ryan Harris
2

Verwenden eines for-loop:

  • Antworten mit 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 .
  • eine leere Liste erstellen, indices
  • Erstellen Sie die Schleife mit for i in range(len(x)):, die im Wesentlichen eine Liste von Indexpositionen durchläuft[0, 1, 2, 3, ..., len(x)-1]
  • Fügen Sie in der Schleife any hinzu 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]
  • Die Funktionen 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.

Verwenden eines while-loopund .index:

  • Mit .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]
Trenton McKinney
quelle
Ihre Selbstdefinition get_indeicesist etwas schneller (~ 15%) als das normale Listenverständnis. Ich versuche es herauszufinden.
Travis
1

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)
Mr. Xcoder
quelle
1

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]
Denis Rasulev
quelle