¿Cómo obtener los últimos elementos de una lista en Python?

Resuelto Nope asked hace 15 años • 5 respuestas

Necesito los últimos 9 números de una lista y estoy seguro de que hay una manera de hacerlo slicing, pero parece que no puedo entenderlo. Puedo obtener los primeros 9 así:

num_list[0:9]
Nope avatar Mar 15 '09 03:03 Nope
Aceptado

Puedes usar números enteros negativos con el operador de corte para eso. Aquí hay un ejemplo que utiliza el intérprete CLI de Python:

>>> a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
>>> a[-9:]
[4, 5, 6, 7, 8, 9, 10, 11, 12]

la línea importante esa[-9:]

winsmith avatar Mar 14 '2009 20:03 winsmith

un índice negativo contará desde el final de la lista, entonces:

num_list[-9:]
cobbal avatar Mar 14 '2009 20:03 cobbal

rebanar

La división de Python es una operación increíblemente rápida y es una forma práctica de acceder rápidamente a partes de sus datos.

La notación de corte para obtener los últimos nueve elementos de una lista (o cualquier otra secuencia que la admita, como una cadena) se vería así:

num_list[-9:]

Cuando veo esto, leo la parte entre paréntesis como "noveno desde el final, hasta el final". (En realidad, lo abrovio mentalmente como "-9, activado")

Explicación:

La notación completa es

sequence[start:stop:step]

Pero los dos puntos son lo que le dice a Python que le estás dando una porción y no un índice regular. Es por eso que la forma idiomática de copiar listas en Python 2 es

list_copy = sequence[:]

Y eliminarlos es con:

del my_list[:]

(Las listas obtienen list.copyy list.clearen Python 3.)

¡Dale a tus rebanadas un nombre descriptivo!

Puede resultarle útil separar la formación del segmento de pasarla al list.__getitem__método ( eso es lo que hacen los corchetes ). Incluso si no es nuevo en esto, mantiene su código más legible para que otras personas que tengan que leerlo puedan entender más fácilmente lo que está haciendo.

Sin embargo, no puede simplemente asignar algunos números enteros separados por dos puntos a una variable. Necesitas usar el objeto de corte:

last_nine_slice = slice(-9, None)

El segundo argumento, None, es obligatorio, de modo que el primer argumento se interpreta como el startargumento , de lo contrario sería el stopargumento .

Luego puedes pasar el objeto de corte a tu secuencia:

>>> list(range(100))[last_nine_slice]
[91, 92, 93, 94, 95, 96, 97, 98, 99]

islice

islicedesde el módulo itertools es otra forma posiblemente eficaz de conseguir esto. isliceno toma argumentos negativos, por lo que lo ideal es que su iterable tenga un __reversed__método especial, que la lista tiene, por lo que primero debe pasar su lista (o iterable con __reversed__) a reversed.

>>> from itertools import islice
>>> islice(reversed(range(100)), 0, 9)
<itertools.islice object at 0xffeb87fc>

islice permite una evaluación diferida de la canalización de datos, por lo que para materializar los datos, páselo a un constructor (como list):

>>> list(islice(reversed(range(100)), 0, 9))
[99, 98, 97, 96, 95, 94, 93, 92, 91]
Russia Must Remove Putin avatar Jul 07 '2014 22:07 Russia Must Remove Putin

Los últimos 9 elementos se pueden leer de izquierda a derecha usando numlist[-9:], o de derecha a izquierda usando numlist[:-10:-1], como desee.

>>> a=range(17)
>>> print a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
>>> print a[-9:]
[8, 9, 10, 11, 12, 13, 14, 15, 16]
>>> print a[:-10:-1]
[16, 15, 14, 13, 12, 11, 10, 9, 8]
Nikwin avatar Mar 15 '2009 04:03 Nikwin

Aquí hay varias opciones para obtener los elementos "cola" de un iterable:

Dado

n = 9
iterable = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Salida deseada

[2, 3, 4, 5, 6, 7, 8, 9, 10]

Código

Obtenemos el último resultado usando cualquiera de las siguientes opciones:

from collections import deque
import itertools

import more_itertools


# A: Slicing
iterable[-n:]


# B: Implement an itertools recipe
def tail(n, iterable):
    """Return an iterator over the last *n* items of *iterable*.

        >>> t = tail(3, 'ABCDEFG')
        >>> list(t)
        ['E', 'F', 'G']

    """
    return iter(deque(iterable, maxlen=n))
list(tail(n, iterable))


# C: Use an implemented recipe, via more_itertools
list(more_itertools.tail(n, iterable))


# D: islice, via itertools
list(itertools.islice(iterable, len(iterable)-n, None))


# E: Negative islice, via more_itertools
list(more_itertools.islice_extended(iterable, -n, None))

Detalles

  • R. El corte tradicional de Python es inherente al lenguaje. Esta opción funciona con secuencias como cadenas, listas y tuplas. Sin embargo, este tipo de corte no funciona en iteradores , por ejemplo iter(iterable).
  • B. Una itertoolsreceta . Está generalizado para funcionar en cualquier iterable y resuelve el problema del iterador en la última solución. Esta receta debe implementarse manualmente ya que no está incluida oficialmente en el itertoolsmódulo.
  • C. Muchas recetas, incluida la última herramienta (B), se han implementado convenientemente en paquetes de terceros. La instalación e importación de estas bibliotecas evita la implementación manual. Una de estas bibliotecas se llama more_itertools(instalar mediante > pip install more-itertools); ver more_itertools.tail.
  • D. Un miembro de la itertoolsbiblioteca. Tenga en cuenta que itertools.islice no admite el corte negativo .
  • E. Se implementa otra herramienta more_itertoolsque se generaliza itertools.islicepara admitir el corte negativo; ver more_itertools.islice_extended.

¿Cuál uso?

Eso depende . En la mayoría de los casos, el corte (opción A, como se menciona en otras respuestas) es la opción más simple, ya que está integrado en el lenguaje y admite la mayoría de los tipos iterables. Para iteradores más generales, utilice cualquiera de las opciones restantes. Tenga en cuenta que las opciones C y E requieren la instalación de una biblioteca de terceros, lo que puede resultar útil para algunos usuarios.

pylang avatar Aug 22 '2017 19:08 pylang