¿Por qué este código iterativo de crecimiento de lista da IndexError: índice de asignación de lista fuera de rango?

194

Por favor considere el siguiente código:

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

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

print j

El resultado (Python 2.6.6 en Win 7 de 32 bits) es:

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

Supongo que es algo simple que no entiendo. ¿Alguien puede aclararlo?

Vladan
fuente
66
appendes la solución adecuada para su caso de uso, sin embargo, hay un método de inserción en la lista de Python que puede insertarse directamente en la i-ésima posición en la lista. j.insert(k, l)
opensourcegeek
¿Puedo preguntar por qué no funcionaría la solución de OP? ¿Por qué usar append?
Helen

Respuestas:

317

jes una lista vacía, pero está intentando escribir en el elemento [0]en la primera iteración, que aún no existe.

En su lugar, intente lo siguiente para agregar un nuevo elemento al final de la lista:

for l in i:
    j.append(l)

Por supuesto, nunca haría esto en la práctica si todo lo que quisiera hacer fuera copiar una lista existente. Simplemente harías:

j = list(i)

Alternativamente, si desea utilizar la lista de Python como una matriz en otros idiomas, puede crear previamente una lista con sus elementos establecidos en un valor nulo ( Noneen el ejemplo a continuación), y luego, sobrescribir los valores en posiciones específicas:

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

Lo que debe darse cuenta es que un listobjeto no le permitirá asignar un valor a un índice que no existe.

Steve Mayne
fuente
2
Vale, muchas gracias. No sabía cuál elogiar, ya que hay tres respuestas casi iguales. Esto es más descriptivo, creo. Saludos
Vladan
Puedo ver que esto puede ser muy confuso para aquellos que vienen de otros lenguajes como PHP o C. j es un tipo de lista, no una matriz. Con el tipo de lista, no creo que esto sea subscriptable. Muy confuso si viene de otros idiomas.
Nguai al
@Nguaial El tipo de lista es subscriptible, pero solo puede acceder a elementos que ya existen; no puede crear un elemento intentando escribir en un índice que está fuera de rango. j [0] = "foo" funcionará si la lista ya tiene al menos un elemento.
Steve Mayne
52

Su otra opción es inicializar j:

j = [None] * len(i)
Rsh
fuente
3
Desea usar len (i) en lugar de max.
Steve Mayne
25

Hacer en j.append(l)lugar de j[k] = ly evitar ken absoluto.

Khachik
fuente
2
Una forma más corta (¿más pitónica?) Podría serj+=[l]
Oleh Prypin el
2
@BlaXpirit: Creo que supondrá una carga para el recolector de basura.
khachik
2
@BalXpirit: dado que solo guarda unos pocos caracteres (especialmente porque necesita agregar espacios para que sea aceptable) y eso .appendes mucho más común (quizás por una razón, creo que es un poco más fácil de comprender), no realmente superior de cualquier manera. (Editar @ khachik: No, +=modifica en el lugar)
15

También podría usar una lista de comprensión:

j = [l for l in i]

o haga una copia usando la declaración:

j = i[:]
Jason Sundram
fuente
esa segunda construcción está ordenada
javadba
2
Si el único objetivo es copiar la lista, simplemente puede decir j = list (i) Creo que la pregunta es más sobre el comportamiento de las listas, en lugar de necesitar específicamente una forma de copiar elementos.
Steve Mayne
10
j.append(l)

También evite usar "L" en minúsculas porque es fácil confundirlas con 1

Tom
fuente
7

Creo que el método de inserción de Python es lo que estás buscando:

Inserta el elemento x en la posición i. list.insert (i, x)

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

array.insert(1,20)

print(array)

# prints [1,2,20,3,4,5]
agua
fuente
1
No tiene sentido usar insertcuándo appendse proporcionó específicamente para este propósito.
holdenweb
En un punto de información, su código de hecho se imprime [1, 20, 2, 3, 4, 5].
holdenweb
Insertó en el índice 1, desplazando los índices 1 y en adelante. El valor insertado no termina en el índice 2. Iist.insert () solo es realmente necesario cuando no desea agregar el elemento al final de la lista; la pregunta aquí hace exactamente eso, por lo que es preferible list.append ().
Martijn Pieters
En realidad, por qué respondo así a esta pregunta también me sorprende: D No sé lo que pensé :) Esto es exactamente "list.append ()", que es la respuesta aceptada. Creo que ayuda a las personas o da una idea para resolver sus problemas, por lo que obtiene 5 visitas.
agua
5

Podría usar un diccionario (similar a una matriz asociativa) para 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

imprimirá:

{0: 1, 1: 2, 2: 3, 3: 5, 4: 8, 5: 13}
Cedric
fuente
Para las indicaciones consecutivas que comienzan en 0, una asignación suele ser la estructura de datos incorrecta , especialmente cuando las asignaciones no tienen segmentación o inversión ya que no están destinadas a transmitir ningún orden específico.
Martijn Pieters
2

Una forma más:

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

En este caso jserá una matriz numpy

Alex
fuente
0

Quizás necesites extender ()

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