2011-07-01 15 views
10

¿Existe alguna manera directa de obtener el índice de un ítem que acabo de agregar a una lista? Necesito hacer un seguimiento del último elemento agregado.Obtenga el índice del ítem recientemente agregado

me ocurrió con dos soluciones posibles:

# Workaround 1 
# The last added is the one at index len(li) - 1 
>> li = ['a', 'b', 'c',] 
>> li.append('d') 
>> last_index = len(li) - 1 
>> last_item = li[len(li) - 1] 

# Workaround 2 
# Use of insert at index 0 so I know index of last added 
>> li = ['a', 'b', 'c',] 
>> li.insert(0, 'd') 
>> last_item = li[0] 

¿Hay un truco para obtener el índice de un elemento añadido?

Si no la hay, ¿cuál de las anteriores usaría y por qué? ¿Alguna solución diferente que sugiera?

Respuesta

16

li[-1] es el último elemento de la lista, y por lo tanto el que fue más recientemente anexa a su fin:

>>> li = [1, 2, 3] 
>>> li.append(4) 
>>> li[-1] 
4 

Si necesita el índice, no el artículo, después len(li) - 1 es muy bien, y muy eficiente (desde len(li) se calcula en tiempo constante - ver más abajo)


en la fuente de CPython, len para listas es enlazada con la función list_length en Objects/listobject.c:

static Py_ssize_t 
list_length(PyListObject *a) 
{ 
    return Py_SIZE(a); 
} 

Py_SIZE es sólo una macro para acceder al atributo de tamaño de todos los objetos de Python, definido en Include/object.h:

#define Py_SIZE(ob)  (((PyVarObject*)(ob))->ob_size) 

Por lo tanto, len(lst) es esencialmente una sola referencia a un puntero.

+0

Mucho sobre la eficiencia de len (li). ¡Gracias! – romeroqj

+0

@horhay: dado que te gustó, agregué algunos detalles más tomados directamente * de la fuente * –

+0

¡gracias por profundizar! :) – romeroqj

3

Puede indexar listas desde cualquier lado. El índice del último elemento siempre es -1, no necesita llamar al len. Insertar repetidamente al principio es muy ineficiente (requiere que todos los elementos de la lista se muevan un lugar hacia abajo).

+2

Según tengo entendido, OP quería un índice "reutilizable/absoluto". En otras palabras, un índice que podría usarse para rastrear el valor incluso una vez que otros elementos se agregarán a la lista (-1 es "no reutilizable/relativo" ... pero ¿tal vez estoy pensando demasiado? – mac

+0

@mac No voy a ir muy lejos, en realidad creo que tu sugerencia es excelente, pero a la larga, tendré que lidiar con las limitaciones que mencionaste sobre los espacios de nombres y la preservación de ese índice a través de devoluciones. Por ahora @Eli Bendersky aclaración sobre la eficacia de len (li) está bien ¡Agradezca su ayuda! – romeroqj

3

Una tercera posible solución sería la subclase list y anular el método append, de modo que se almacene automáticamente en una propiedad como mylist.last_added cada vez que lo llame.

Este enfoque - si se extiende a otros métodos de listas - ofrece la ventaja de que usted podría crear una clase donde se hará un seguimiento del índice del último elemento añadido independientemente del método utilizado (insert, append, o asignación simple de mylist[some_index] = some_value).

Otra ventaja de incorporar esta información en el objeto de lista es que la pasará sin tener que preocuparse por los espacios de nombres (para que pueda recuperarla incluso si su lista se pasa por return o yield, por ejemplo)

+0

Sugiero que se subclassing [collections.MutableSequence] (http://docs.python.org/library/collections.html#abcs-abstract-base-classes) [ABC] (http://en.wikipedia.org/wiki/Abstract_base_class) en lugar de list. Esto hace que sea más fácil "capturar" cada forma en que se use su lista extendida, y solo necesita implementar 5 métodos. Vea [esto] (http://stackoverflow.com/questions/241141/python-lazy-list/5104787#5104787) respuesta (enchufe desvergonzado). –

Cuestiones relacionadas