Perché questo codice iterativo che aumenta la lista fornisce IndexError: indice di assegnazione delle liste fuori intervallo?


194

Si prega di considerare il seguente codice:

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

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

print j

L'output (Python 2.6.6 su Win 7 a 32 bit) è:

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

Immagino sia qualcosa di semplice che non capisco. Qualcuno può chiarirlo?


7
appendè la soluzione giusta per il tuo caso d'uso, tuttavia esiste un metodo di inserimento nell'elenco Python che può essere inserito direttamente nella posizione 1 dell'elenco. j.insert(k, l)
opensourcegeek,

Posso chiedere, perché la soluzione di OP non dovrebbe funzionare? Perché usare Append?
Helen,

Risposte:


318

jè un elenco vuoto, ma stai tentando di scrivere nell'elemento [0]nella prima iterazione, che non esiste ancora.

Prova invece quanto segue, per aggiungere un nuovo elemento alla fine dell'elenco:

for l in i:
    j.append(l)

Naturalmente, non lo faresti mai in pratica se tutto ciò che volevi fare fosse copiare un elenco esistente. Dovresti semplicemente fare:

j = list(i)

In alternativa, se si desidera utilizzare l'elenco Python come un array in altre lingue, è possibile pre-creare un elenco con i suoi elementi impostati su un valore null ( Nonenell'esempio seguente) e, successivamente, sovrascrivere i valori in posizioni specifiche:

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

La cosa da capire è che un listoggetto non ti permetterà di assegnare un valore a un indice che non esiste.


2
Ok grazie mille. Non sapevo quale elogiare perché ci sono tre risposte quasi uguali. Questo è il più descrittivo penso. Saluti
Vladan,

Vedo che questo può essere molto confuso per coloro che provengono da altre lingue come PHP o C. j è un tipo di elenco, non un array. Con il tipo di elenco, non penso che sia sottoscrivibile. Molto confuso se proveniente da altre lingue.
Nguai al

@Nguaial Il tipo di elenco è sottoscrivibile, ma è possibile accedere solo agli elementi già esistenti: non è possibile creare un elemento tentando di scrivere su un indice fuori intervallo. j [0] = "pippo" funzionerà se l'elenco ha già almeno un elemento.
Steve Mayne,

52

L'altra opzione è di inizializzare j:

j = [None] * len(i)

3
Si desidera utilizzare len (i) anziché max.
Steve Mayne,

25

Fare j.append(l)invece di j[k] = led evitare kaffatto.


2
Un modo più breve (più Pythonic?) Potrebbe esserej+=[l]
Oleh Prypin

2
@BlaXpirit: penso che graverà sul garbage collector.
Khachik,

2
@BalXpirit: dato che consente di salvare solo pochi caratteri (soprattutto perché è necessario aggiungere spazi affinché sia ​​accettabile) e che .appendè di gran lunga più comune (forse per un motivo - penso che sia leggermente più facile da capire), non molto superiore in ogni modo. (Modifica @khachik: No, +=modifica sul posto)

15

È inoltre possibile utilizzare una comprensione dell'elenco:

j = [l for l in i]

o crearne una copia usando la dichiarazione:

j = i[:]

quella seconda costruzione è ordinata
javadba,

2
Se l'unico obiettivo è copiare l'elenco, puoi semplicemente dire j = list (i) Penso che la domanda riguardi più il comportamento degli elenchi, piuttosto che il bisogno specifico di un modo per copiare elementi.
Steve Mayne,

10
j.append(l)

Evita anche di usare le "L" minuscole perché è facile confonderle con le 1


7

Penso che l' inserto del metodo Python sia quello che stai cercando:

Inserisce l'elemento x nella posizione i. list.insert (i, x)

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

array.insert(1,20)

print(array)

# prints [1,2,20,3,4,5]

1
Non ha senso utilizzare insertquando è appendstato fornito appositamente per questo scopo.
holdenweb,

Per quanto riguarda le informazioni, il codice viene infatti stampato [1, 20, 2, 3, 4, 5].
holdenweb,

Hai inserito l'indice 1, spostando gli indici 1 e successivi. Il valore inserito non termina all'indice 2. Iist.insert () è veramente necessario solo quando non si desidera aggiungere l'elemento alla fine dell'elenco; la domanda qui fa esattamente questo, quindi è preferibile list.append ().
Martijn Pieters

In realtà perché rispondo a questa domanda in questo modo sono anche sorpreso: D Non so cosa ho pensato :) Questo è esattamente "list.append ()" che è la risposta accettata. Penso che aiuti le persone o che dia un'idea per risolvere i loro problemi in modo da ottenere 5 risultati.
Mehmet Kagan Kayaalp,

5

È possibile utilizzare un dizionario (simile a un array associativo) per j

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

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

print j

stamperà:

{0: 1, 1: 2, 2: 3, 3: 5, 4: 8, 5: 13}

Per le indicazioni consecutive a partire da 0, una mappatura è generalmente una struttura di dati errata , specialmente quando le mappature non hanno suddivisione o inversione in quanto non intendono trasmettere alcun ordine specifico.
Martijn Pieters

2

Un altro modo:

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

In questo caso j sarà un array intorpidito


0

Forse hai bisogno di extension ()

i=[1,3,5,7]
j=[]
j.extend(i)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.