Jak zdobyć ostatnie elementy listy w Pythonie?

288

Potrzebuję ostatnich 9 liczb z listy i jestem pewien, że istnieje sposób, aby to zrobić przy pomocy krojenia, ale nie mogę tego zrobić. Pierwsze 9 mogę uzyskać w ten sposób:

num_list[0:9]
nie
źródło

Odpowiedzi:

519

W tym celu można użyć ujemnych liczb całkowitych z operatorem krojenia. Oto przykład z użyciem interpretera CLI w Pythonie:

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

ważną linią jest a[-9:]

zwycięzca
źródło
11
Zauważ, że tak -0jest 0. a[-0:]Zwraca więc całe a, a nie ostatnie zero elementów []. Do ochrony zera możesz użyć a[-n:] if n > 0 else [].
nekketsuuu
93

indeks ujemny będzie liczony od końca listy, więc:

num_list[-9:]
cobbal
źródło
53

Krajanie na plastry

Wycinanie w języku Python jest niezwykle szybką operacją i jest poręcznym sposobem szybkiego dostępu do części danych.

Notacja plastra, aby uzyskać ostatnie dziewięć elementów z listy (lub dowolnej innej sekwencji, która ją obsługuje, na przykład ciąg) wyglądałaby następująco:

num_list[-9:]

Kiedy to widzę, czytam tę część w nawiasach jako „9. od końca, do końca”. (Właściwie to w myślach nazywam to „-9, on”)

Wyjaśnienie:

Pełna notacja to

sequence[start:stop:step]

Ale dwukropek mówi Pythonowi, że dajesz mu plasterek, a nie zwykły indeks. Właśnie dlatego idiomatycznym sposobem kopiowania list w Pythonie 2 jest

list_copy = sequence[:]

I ich usunięcie polega na:

del my_list[:]

(Listy pobierają list.copyiw list.clearPythonie 3).

Nadaj swoim plasterkom opisową nazwę!

Przydatne może być oddzielenie formowania wycinka od przekazania go do list.__getitem__metody ( to właśnie robią nawiasy kwadratowe ). Nawet jeśli nie jesteś nowy, kod jest bardziej czytelny, dzięki czemu inni, którzy mogą przeczytać kod, mogą łatwiej zrozumieć, co robisz.

Nie można jednak po prostu przypisać zmiennej do liczb całkowitych oddzielonych dwukropkami. Musisz użyć obiektu plasterka:

last_nine_slice = slice(-9, None)

Drugi argument, Nonejest wymagany, aby pierwszy argument był interpretowany jako startargument, w przeciwnym razie byłby to stopargument .

Następnie możesz przekazać obiekt plasterka do swojej sekwencji:

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

islice

islicez modułu itertools to kolejny możliwy sposób na uzyskanie tego. islicenie ma negatywnych argumentów, więc idealnie swój iterable posiada __reversed__specjalny sposób - co lista nie ma - więc trzeba najpierw zdać listy (lub z iterable __reversed__) do reversed.

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

islice pozwala na leniwą ocenę potoku danych, więc aby zmaterializować dane, przekaż je konstruktorowi (jak list):

>>> list(islice(reversed(range(100)), 0, 9))
[99, 98, 97, 96, 95, 94, 93, 92, 91]
Aaron Hall
źródło
Twój skrót mentalny jest bardzo pomocny
Swanky Coder
40

Ostatnie 9 elementów można odczytać od lewej do prawej za pomocą numlist [-9:] lub od prawej do lewej za pomocą numlist [: - 10: -1], jak chcesz.

>>> 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
źródło
6

Oto kilka opcji uzyskania „ogona” elementów iterowalnych:

Dany

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

Pożądane wyjście

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

Kod

Ten drugi wynik uzyskujemy za pomocą jednej z następujących opcji:

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))

Detale

  • A. Tradycyjne krojenie w Pythonie jest nieodłączne od języka. Ta opcja działa z ciągami, takimi jak ciągi, listy i krotki. Ten rodzaj krojenia nie działa jednak na iteratorach , npiter(iterable) .
  • B. itertoolsPrzepis . Uogólniono go do pracy na dowolnej iterowalnej i rozwiązuje problem iteratora w ostatnim rozwiązaniu. Ten przepis należy wprowadzić ręcznie, ponieważ nie jest on oficjalnie zawarty witertools module.
  • C. Wiele przepisów, w tym drugie narzędzie (B), zostało wygodnie zaimplementowanych w pakietach stron trzecich. Zainstalowanie i zaimportowanie tych bibliotek eliminuje ręczne wdrażanie. Jedna z tych bibliotek nazywa się more_itertools(zainstaluj przez > pip install more-itertools); widziećmore_itertools.tail .
  • D. Członek itertoolsbiblioteki. Uwaga: itertools.islice nie obsługuje negatywnego krojenia .
  • E. Wprowadzono inne narzędzie, more_itertoolsktóre uogólnia w itertools.islicecelu obsługi negatywnego krojenia; zob more_itertools.islice_extended.

Z którego korzystam?

To zależy . W większości przypadków krojenie (opcja A, jak wspomniano w innych odpowiedziach) jest najprostszą opcją, ponieważ jest wbudowana w język i obsługuje większość iterowalnych typów. W przypadku bardziej ogólnych iteratorów użyj dowolnej z pozostałych opcji. Uwaga: opcje C i E wymagają zainstalowania biblioteki innej firmy, co niektórzy użytkownicy mogą uznać za przydatną.

pylang
źródło