Por que esse código iterativo de crescimento de lista deixa IndexError: índice de atribuição de lista fora do intervalo?


194

Por favor, considere o seguinte código:

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

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

print j

A saída (Python 2.6.6 no Win 7 de 32 bits) é:

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

Eu acho que é algo simples que eu não entendo. Alguém pode esclarecer isso?


6
appendé a solução certa para o seu caso de uso, no entanto, existe um método de inserção na lista python que pode ser inserido diretamente na i-ésima posição na lista. j.insert(k, l)
Opensourcegeek

Posso perguntar, por que a solução da OP não funcionaria? Por que usar anexar?
Helen

Respostas:


317

jé uma lista vazia, mas você está tentando gravar no elemento [0]na primeira iteração, que ainda não existe.

Tente o seguinte, para adicionar um novo elemento ao final da lista:

for l in i:
    j.append(l)

Obviamente, você nunca faria isso na prática se tudo que você queria fazer era copiar uma lista existente. Você apenas faria:

j = list(i)

Como alternativa, se você quiser usar a lista Python como uma matriz em outros idiomas, poderá pré-criar uma lista com seus elementos configurados para um valor nulo ( Noneno exemplo abaixo) e, posteriormente, substituir os valores em posições 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

A única coisa a perceber é que um listobjeto não permitirá que você atribua um valor a um índice que não existe.


2
Ok, muito obrigado. Não sabia qual deles louvar, pois há três respostas quase iguais. Isso é muito descritivo, eu acho. Cheers
Vladan

Percebo que isso pode ser muito confuso para quem vem de outras linguagens como PHP ou C. j é um tipo de lista, não uma matriz. Com o tipo de lista, não acho que isso possa ser subscrito. Muito confuso se vier de outras línguas.
Nguai al

@Nguaial O tipo de lista é subscrito, mas você pode acessar apenas elementos que já existem - você não pode criar um elemento tentando gravar em um índice que está fora do intervalo. j [0] = "foo" funcionará se a lista já tiver pelo menos um elemento.
27519 Steve Stevene

52

Sua outra opção é inicializar j:

j = [None] * len(i)

3
Você deseja usar len (i) em vez de máx.
Steve Mayne

25

Faça ao j.append(l)invés de j[k] = le evite k.


2
A (? Mais Pythonic) caminho mais curto pode serj+=[l]
Oleh Prypin

2
@BlaXpirit: Acho que isso sobrecarregará o coletor de lixo.
Khachik

2
@BalXpirit: Dado que apenas alguns caracteres são salvos (especialmente porque você precisa adicionar espaços para que seja aceitável) e isso .appendé muito mais comum (talvez por uma razão - acho que é um pouco mais fácil de entender), não muito superior de qualquer maneira. (Edit @khachik: Não, +=modifica no local)

15

Você também pode usar uma compreensão de lista:

j = [l for l in i]

ou faça uma cópia usando a instrução:

j = i[:]

que a segunda construção é arrumada
javadba 17/02

2
Se o único objetivo é copiar a lista, você pode simplesmente dizer j = list (i) Acho que a pergunta é mais sobre o comportamento das listas, do que precisar especificamente de uma maneira de copiar elementos.
Steve Mayne

10
j.append(l)

Evite também usar "L" minúsculo, pois é fácil confundi-lo com 1's


7

Eu acho que a inserção do método Python é o que você está procurando:

Insere o elemento x na posição 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
Não faz sentido usar insertquando appendfoi fornecido especificamente para esse fim.
holdenweb

Em um ponto de informação, seu código é impresso [1, 20, 2, 3, 4, 5].
holdenweb

Você inseriu no índice 1, deslocando os índices 1 e em diante. O valor inserido não termina no índice 2. Iist.insert () é realmente necessário apenas quando você não deseja adicionar o item no final da lista; a pergunta aqui faz exatamente isso, então list.append () é preferível.
Martijn Pieters

Na verdade, por que respondo a essa pergunta dessa maneira, também estou surpreso: D Não sei o que pensei :) É exatamente "list.append ()", que é a resposta aceita. Eu acho que ajuda as pessoas ou dá uma idéia para resolver seus problemas, obtendo 5 hits.
água

5

Você poderia usar um dicionário (semelhante a uma matriz associativa) 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

irá imprimir:

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

Para indicações consecutivas começando em 0, um mapeamento geralmente é a estrutura de dados incorreta , especialmente quando os mapeamentos não têm fatias ou reversões, pois não se destinam a transmitir nenhuma ordem específica.
Martijn Pieters

2

Mais uma maneira:

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

Nesse caso j, haverá uma matriz numpy


0

Talvez você precise estender ()

i=[1,3,5,7]
j=[]
j.extend(i)
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.