2009-05-15 5 views
23

Es esto posible:¿Completando una lista/matriz por índice en Python?

myList = [] 

myList[12] = 'a' 
myList[22] = 'b' 
myList[32] = 'c' 
myList[42] = 'd' 

Cuando lo intento, me sale:

# IndexError: list assignment index out of range # 
+0

myList =() es actua l una tupla, no puede agregar, eliminar o encontrar objetos en una tupla. –

+0

Sí, realmente usé [] en el código, me confundí aquí. –

Respuesta

44

Vas a tener que pre-llenarlo con algo (por ejemplo 0 o None) antes de que pueda indexar:

myList = [None] * 100 # Create list of 100 'None's 
myList[12] = 'a' # etc. 

otra alternativa es utilizar un diccionario en lugar de una lista, como Alex Martelli suggested.

25

Por una "lista escasa" se puede utilizar una vez dict:

mylist = {} 
mylist[12] = 'a' 

etc. Si usted quiere una lista real (inicialícela con [], no(), por supuesto! -) usted necesita llenar las ranuras no establecidas a _some_thing, p. None, por una pequeña función auxiliar o por subclasificación list.

+0

A juzgar por el error, creo que en realidad estaba usando una lista, no una tupla. –

+3

probablemente no sea la mejor práctica llamar a su diccionario 'mylist'. – SilentGhost

+0

Gracias Necesito acceso lineal al artículo, por lo que podré indexar de 1 a n, por lo que no puedo usar el diccionario. –

2

No sin poblar los otros lugares en la lista con algo (como None o una cadena vacía). Intentar insertar un elemento en una lista utilizando el código que escribió daría como resultado un IndexError.

También hay mylist.insert, pero este código:

myList.insert(12,'a') 

le basta con insertar 'a' en la primera posición no ocupada en la lista (que sería 0 usando tu ejemplo).

Entonces, como dije, tiene que haber algo en la lista en los índices 0-11 antes de que pueda insertar algo en myList[12].

+0

De hecho, list.insert() no es una solución correcta, ya que al insertar un elemento se moverán todos los demás índices. – gaborous

2

Si no se conoce el tamaño de la lista antes de tiempo, se puede usar try/except y luego extender la lista de la excepción:

L = [] 
def add(i, s): 
    try: 
     L[i] = s 
    except IndexError: 
     L.extend([None]*(i-len(L)+1)) 
     L[i] = s 

add(12, 'a') 
add(22, 'b') 

----- Actualización - -------------------------------------------
Comentario de Per tgray: Si es probable que su código arroje una excepción la mayor parte del tiempo, debe verificar la longitud de la lista cada vez, y evitar las excepciones:

L = [] 
def add(i, s): 
    size = len(L) 
    if i >= size: 
     L.extend([None]*(i-size+1)) 
     L[i] = s 
+0

Si agrega elementos con índices crecientes, la velocidad probablemente podría mejorarse mediante el uso de una instrucción 'if' en lugar de una 'try-catch'. En este caso, usted atrapará la excepción cada vez, lo cual es más "costoso" que verificar la longitud de L cada vez. – tgray

+0

¿Tiene un enlace a la fuente que indique que es más "caro"? O por cuánto? Eso sería útil. –

+0

Aquí hay un enlace a la fuente de mi comentario: http://paltman.com/2008/jan/18/try-except-performance-in-python-a-simple-test/ – tgray

14

Aquí hay un contenedor de lista rápida que expandirá automáticamente su lista con ceros si intenta asignar un valor a un índice más allá de su longitud.

class defaultlist(list): 

    def __setitem__(self, index, value): 
     size = len(self) 
     if index >= size: 
     self.extend(0 for _ in range(size, index + 1)) 

     list.__setitem__(self, index, value) 

Ahora usted puede hacer esto:

>>> a = defaultlist([1,2,3]) 
>>> a[1] = 5 
[1,5,3] 
>>> a[5] = 10 
[1,5,3,0,0,10] 
+0

muy bueno! simple y elegante, gracias –

1

Sólo en caso de que alguien necesita, me di cuenta de una soluction para mi problema, necesitaba Calc un montón de factoriales, algunos de ellos podría repetirse, así que aquí está mi solución:

factorials = {} 

def calcFact(v): 
    try: 
     return factorials[v] 
    except KeyError: 
     factorials[v] = math.factorial(v) 
     return factorials[v] 

caso_prueba:

calcFact(99000) 
calcFact(90900) 
calcFact(90090) 
calcFact(90009) 
calcFact(90009) #repeated 
calcFact(90009) #repeated 

Resultados:

Repetición Calc matemática: 1.576 s

Usando el código anterior (una lista para almacenar valores repetidos): 1.011 s

+0

Esto no proporciona una respuesta a la pregunta. Para criticar o solicitar aclaraciones de un autor, deje un comentario debajo de su publicación. – phineas

+0

@phineas como dije en mi respuesta, esto era algo que tenía que resolver, y eso estaba relacionado con "Completar una lista/matriz por índice" como puede observar al leer el código. Esta es una manera de resolver la pregunta, pero con un ejemplo diferente. –

Cuestiones relacionadas