IndexError: list index out of range

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Amani
User
Beiträge: 1
Registriert: Montag 23. Oktober 2023, 08:42

Hallo,

also ich habe folgendes Problem. Ich möchte aus einer Textdatei Daten auslesen. Diese speichere ich dann in einer zweidimensionalen Liste. Danach suche ich in der Liste nach speziellen Schlüsselwörter, um bestimmte Werte, die nach dem Schlüsselwörtern kommen, in einer Variable zu speichern.
So sieht mein Code dafür aus:

Code: Alles auswählen

data: list[list[str]] = [line.split() for line in fh]
        rangeOne = len(data) - 1
        for i in range(rangeOne):
            rangeTwo = len(data[i]) - 1
            if rangeTwo == -1:
                rangeTwo = 0
            for v in range(rangeTwo):
                if data[i][v] == "Kompletter":
                    start = True
                    komplett = data[i][v+1] 
Jedoch bekomme ich an der Stelle "if data[v] == "Kompletter":" für das v die Fehlermeldung "IndexError: list index out of range". Ich verstehe allerdings nicht wirklich warum. Wenn ich das Kompletter beispielsweise zu "Steuergerät" ändere, dann bekomme ich keine Fehlermeldung. Ich benutze diesen Code auch in meinem Programm an einer anderer Stelle und da funktioniert er ohne Fehlermeldung.
Ein Ausschnitt der Liste sieht so aus

Code: Alles auswählen

[['Kompletter', 'Scan'], ['Steuergeräte:', '34'], [] ]
Die Liste enthält dementsprechend auch leere Elemente. Aber das hat im anderen Teil des Programms oder wenn ich das Schlüsselwort zu "Steuergerät" ändere, dennoch mit dem obigen Code funktioniert.
Ich weiß nicht wirklich, wie ich das fixen kann.
Ich habe auch anfangs diesen Code probiert:

Code: Alles auswählen

for i in data:
        for v in row:
            if v == "Kompletter":
                return True
                
Jedoch kann ich damit keine Daten einlesen, weil mir die Positionen fehlen, an die die Schlüsselwörter gefunden wurden. Zumindest komme ich nicht darauf, wie man damit Werte einlesen kann.

Ich weiß also nicht wirklich, wie ich dieses Problem beheben soll. :(
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

Dass `data` eine Liste von Listen von Strings ist, ist offensichtlich, das split eine Liste von Strings zurückgibt. Die Typannotation kann also weg. Das macht den Code deutlich lesbarer.
Über einen Index iteriert man nicht. Das ist unpythonisch. Warum wird immer der letzte Eintrag der Liste ignoriert? Eine Liste sollte immer gleichartige Elemente enthalten, wenn aber das letzte Element was besonderes ist, dann hat man ein Problem, wo der Datentyp Liste nicht richtig ist.
Variablennamen werden generell komplett klein geschrieben.

Code: Alles auswählen

data = [line.split() for line in fh]

for entry in data[:-1]:
    for value in entry[:-1]:
        try:
            index = value[:-1].index("Kompletter") + 1
            komplett = value[index]
        except ValueError:
            pass
Wenn die Datei den String "Kompletter Scan" enthält, dann ist das Splitten wohl nicht die richtige Methode, um die Datei zu parsen.
Wenn es sich eigentlich um Key-Value-Paare handelt, dann ist Splitten und die Liste auf diese Art zu durchsuchen der falsche Weg. Eigentlich sollte man die Datei parsen und ein Wörterbuch erzeugen.
Und dabei gleich Zeilen, die kein Key-Value-Paar sind, herausfiltern.
Benutzeravatar
__blackjack__
User
Beiträge: 14053
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Amani: Das sieht nicht so ganz nach Python aus. Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (PascalCase).

Namen sollten keine kryptischen Abkürzungen enthalten oder gar nur daraus bestehen. Der Name soll dem Leser vermitteln was der Wert dahinter im Programm bedeutet, nicht zum rätseln zwingen. `fh` sollte wohl `file` oder `lines` heissen.

Dann sind Schleifen wo die Länge von Sequenzen ermittelt und dann über einen Index iteriert wird, um dann mit dem Index auf die Sequenz zuzugreifen in Python ein „anti pattern“, weil man direkt über die Elemente von Sequenzen iterieren kann. Wenn man da nicht über alle iterieren möchte, oder sich Elemente Paarweise anschauen möchte, gibt es eine ganze Menge Werkzeuge in den Modulen `itertools` (Standardbibliothek) und `more_itertools` (externes Modul).

Der Test auf -1 bei `rangeTwo` ist überflüssig weil der Code nichts am Programmablauf ändert. Ein `range()`-Objekt das eine negative Zahl übergeben bekommt, ist genau wie eines das 0 übergeben bekommt ”leer”:

Code: Alles auswählen

In [150]: len(range(-1))
Out[150]: 0
Ungetestet:

Code: Alles auswählen

from more_itertools import islice_extended, pairwise

...
    
        for words in islice_extended((line.split() for line in lines), -1):
            for word_a, word_b in pairwise(words):
                if word_a == "Kompletter":
                    start = True
                    komplett = word_b
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Antworten