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.