Warum gibt dieser iterative Code mit wachsender Liste IndexError: Listenzuweisungsindex außerhalb des Bereichs?

194

Bitte beachten Sie den folgenden Code:

i = [1, 2, 3, 5, 8, 13]
j = []
k = 0

for l in i:
    j[k] = l
    k += 1

print j

Die Ausgabe (Python 2.6.6 unter Win 7 32-Bit) lautet:

> Traceback (most recent call last): 
>     j[k] = l IndexError: list assignment index out of range

Ich denke, es ist etwas Einfaches, das ich nicht verstehe. Kann jemand es klären?

Vladan
quelle
6
appendist die richtige Lösung für Ihren Anwendungsfall, es gibt jedoch eine Einfügemethode für die Python-Liste, die direkt an die i-te Position in der Liste eingefügt werden kann. j.insert(k, l)
opensourcegeek
Darf ich fragen, warum die Lösung von OP nicht funktionieren würde? Warum anhängen?
Helen

Antworten:

317

jist eine leere Liste, aber Sie versuchen, [0]in der ersten Iteration, die noch nicht vorhanden ist , in ein Element zu schreiben .

Versuchen Sie stattdessen Folgendes, um am Ende der Liste ein neues Element hinzuzufügen:

for l in i:
    j.append(l)

Natürlich würden Sie dies in der Praxis niemals tun, wenn Sie nur eine vorhandene Liste kopieren möchten. Sie würden einfach tun:

j = list(i)

Wenn Sie die Python-Liste wie ein Array in anderen Sprachen verwenden möchten, können Sie alternativ eine Liste vorab erstellen, deren Elemente auf einen Nullwert gesetzt sind ( Noneim folgenden Beispiel), und später die Werte an bestimmten Positionen überschreiben:

i = [1, 2, 3, 5, 8, 13]
j = [None] * len(i)
#j == [None, None, None, None, None, None]
k = 0

for l in i:
   j[k] = l
   k += 1

Zu beachten ist, dass Sie mit einem listObjekt einem nicht vorhandenen Index keinen Wert zuweisen können.

Steve Mayne
quelle
2
OK, vielen Dank. Ich wusste nicht, welche ich loben sollte, da es drei fast gleiche Antworten gibt. Das ist meiner Meinung nach am aussagekräftigsten. Prost
Vladan
Ich kann sehen, dass dies für diejenigen, die aus anderen Sprachen wie PHP oder C kommen, sehr verwirrend sein kann. J ist eine Art Liste, kein Array. Beim Listentyp halte ich dies nicht für abonnierbar. Sehr verwirrend, wenn Sie aus anderen Sprachen kommen.
Nguai al
@Nguaial Der Listentyp ist tiefstellbar, Sie können jedoch nur auf bereits vorhandene Elemente zugreifen. Sie können kein Element erstellen, indem Sie versuchen, in einen Index zu schreiben, der außerhalb des Bereichs liegt. j [0] = "foo" funktioniert, wenn die Liste bereits mindestens ein Element enthält.
Steve Mayne
52

Sie können auch Folgendes initialisieren j:

j = [None] * len(i)
Rsh
quelle
3
Sie möchten len (i) anstelle von max.
Steve Mayne
25

Tun Sie j.append(l)statt j[k] = lund vermeiden Sie küberhaupt.

Khachik
quelle
2
Ein kürzerer (pythonischer?) Weg könnte seinj+=[l]
Oleh Prypin
2
@BlaXpirit: Es wird den Müllsammler belasten, denke ich.
Khachik
2
@BalXpirit: Angesichts der Tatsache, dass nur wenige Zeichen gespeichert werden (zumal Sie Leerzeichen hinzufügen müssen, damit es akzeptabel ist) und dass dies .appendweitaus häufiger vorkommt (vielleicht aus einem Grund - ich denke, es ist etwas einfacher zu verstehen), nicht wirklich überlegen in irgendeiner Weise. (Edit @khachik: Nein, +=ändert an Ort und Stelle)
15

Sie können auch ein Listenverständnis verwenden:

j = [l for l in i]

oder machen Sie eine Kopie davon mit der Anweisung:

j = i[:]
Jason Sundram
quelle
Diese
2
Wenn das einzige Ziel darin besteht, die Liste zu kopieren, können Sie einfach j = list (i) sagen. Ich denke, die Frage bezieht sich eher auf das Verhalten von Listen als darauf, speziell eine Möglichkeit zum Kopieren von Elementen zu benötigen.
Steve Mayne
10
j.append(l)

Vermeiden Sie auch die Verwendung von "L" in Kleinbuchstaben, da diese leicht mit 1 verwechselt werden können

Tom
quelle
7

Ich denke, die Python-Methodeneinfügung ist genau das, wonach Sie suchen:

Fügt Element x an Position i ein. list.insert (i, x)

array = [1,2,3,4,5]

array.insert(1,20)

print(array)

# prints [1,2,20,3,4,5]
Wasser
quelle
1
Es macht keinen Sinn zu verwenden, insertwann appendspeziell für diesen Zweck bereitgestellt wurde.
Holdenweb
In Bezug auf Informationen wird Ihr Code tatsächlich gedruckt [1, 20, 2, 3, 4, 5].
Holdenweb
Sie haben bei Index 1 eingefügt und die Indizes 1 und höher verschoben. Der eingefügte Wert endet nicht bei Index 2. Iist.insert () wird nur dann wirklich benötigt, wenn Sie das Element nicht am Ende der Liste hinzufügen möchten. Die Frage hier macht genau das, also ist list.append () vorzuziehen.
Martijn Pieters
Eigentlich, warum ich diese Frage so beantworte, bin ich auch überrascht: D Weiß nicht, was ich dachte :) Dies ist genau "list.append ()", was die akzeptierte Antwort ist. Ich denke, es hilft Menschen oder gibt eine Idee, um ihre Probleme zu lösen, so dass es 5 Treffer bekommt.
Wasser
5

Sie können ein Wörterbuch (ähnlich einem assoziativen Array) für j verwenden

i = [1, 2, 3, 5, 8, 13]
j = {} #initiate as dictionary
k = 0

for l in i:
    j[k] = l
    k += 1

print j

wird drucken:

{0: 1, 1: 2, 2: 3, 3: 5, 4: 8, 5: 13}
Cedric
quelle
Für aufeinanderfolgende Anzeigen ab 0 ist eine Zuordnung normalerweise die falsche Datenstruktur, insbesondere wenn Zuordnungen kein Schneiden oder Umkehren aufweisen, da sie keine bestimmte Reihenfolge vermitteln sollen.
Martijn Pieters
2

Noch ein Weg:

j=i[0]
for k in range(1,len(i)):
    j = numpy.vstack([j,i[k]])

In diesem Fall handelt jes sich um ein Numpy-Array

Alex
quelle
0

Vielleicht brauchen Sie verlängern ()

i=[1,3,5,7]
j=[]
j.extend(i)
Fred Moo
quelle