Uzyskiwanie ostatniego elementu listy


Odpowiedzi:


3099

some_list[-1] jest najkrótszym i najbardziej pytonicznym.

W rzeczywistości możesz zrobić znacznie więcej dzięki tej składni. some_list[-n]Składnia pobiera element uruchamiany n-tym ostatnim. Więc some_list[-1]dostaje ostatni element, some_list[-2]dostaje od drugiego do ostatniego itd., Aż do some_list[-len(some_list)], co daje pierwszy element.

W ten sposób można również ustawić elementy listy. Na przykład:

>>> some_list = [1, 2, 3]
>>> some_list[-1] = 5 # Set the last element
>>> some_list[-2] = 3 # Set the second to last element
>>> some_list
[1, 3, 5]

Zauważ, że uzyskanie elementu listy według indeksu spowoduje podniesienie, IndexErrorjeśli oczekiwany element nie istnieje. Oznacza to, że some_list[-1]zgłosi wyjątek, jeśli some_listjest pusty, ponieważ pusta lista nie może zawierać ostatniego elementu.


6
Tęsknię za czymś takim some_list.last- to byłaby piękna linia kodu
Dmitry P.

256

Jeśli twoje str()lub list()obiekty mogą być puste jako takie: astr = ''lub alist = [], wtedy możesz chcieć użyć alist[-1:]zamiast alist[-1]dla „identyczności” obiektu.

Znaczenie tego jest następujące:

alist = []
alist[-1]   # will generate an IndexError exception whereas 
alist[-1:]  # will return an empty list
astr = ''
astr[-1]    # will generate an IndexError exception whereas
astr[-1:]   # will return an empty str

Rozróżnia się tutaj to, że zwracanie pustego obiektu listy lub pustego obiektu str jest bardziej „ostatnim elementem” - bardziej niż obiektem wyjątku.


25
Przegłosowano, ponieważ uważam, że rdzeń tej odpowiedzi jest nieprawidłowy. Uzyskiwanie listy, gdy chcesz, aby element tylko opóźniał nieuchronny „indeks listy poza zakresem” - i to powinno się zdarzyć, gdy próbujesz uzyskać element z pustej listy. W przypadku ciągów astr [-1:] może być prawidłowym podejściem, ponieważ zwraca ten sam typ co astr [-1], ale nie sądzę, że „:” pomaga radzić sobie z pustymi listami (a pytanie dotyczy list) . Jeśli chodzi o użycie „alist [-1:]” jako warunku zamiast „len (alist)> 0”, myślę, że użycie o wiele później jest bardziej czytelne. (chętnie głosuję, jeśli coś przegapię)
Stan Kurdziel

9
Twój głos jest zrozumiały i ważny. Uważam jednak, że istnieją dwa podstawowe obozy, dla których przeznaczone są obiekty wyjątkowe. Pewne jest to, że wyjątki zatrzymują Twoją aplikację. Jeden obóz używa wyjątków w klauzulach try, ponieważ drugi obóz użyłby zamiast tego struktury if len (alist)> 0:. W każdym razie wyjątkami są obiekty, które zatrzymują Twój kod. I jako takie są dla mnie mniejszym obiektem sekwencji, jak wtedy zwrócony ciąg „zerowy”, który nie zatrzymuje twojego kodu. Wolę używać klauzul JEŻELI do testowania obiektów „zerowych” zamiast obiektów, które zatrzymują mój kod, który uprzedzam za pomocą klauzuli try.
DevPlayer,

6
Pozytywnie oceniany, ponieważ składnia wycinka jest warta dyskusji, jednak zgadzam się z @StanKurdziel, że morfologia jest nieprawidłowa, po prostu przesuwasz słupek bramki - odkryłem, że moje własne rozwiązanie było związane z podstawowym użyciem „dodaj to do listy, jeśli nie zrobiłeś tego „już go dodaj” (wykresy liniowe delta), więc połączone wyrażenie if len(my_vector) == 0 or my_vector[-1] != update_valjest wykonalnym wzorcem. ale z pewnością nie jest to rozwiązanie globalne - fajnie byłoby mieć formę składni, w której żaden nie był wynikiem
Mark Mullin

17
xs[-1] if xs else None
Gabriel

2
Dlaczego miałbyś „unikać” błędu IndexError? Jeśli spróbujesz zaindeksować pustą listę lub ciąg, otrzymasz wyjątek. Jeśli chcesz obsłużyć ten wyjątek, użyj try / wyjątek - po to jest.
Chris Johnson

93

Możesz także:

alist.pop()

To zależy od tego, co chcesz zrobić z listą, ponieważ pop()metoda usunie ostatni element.


70

Najprostszym sposobem wyświetlenia ostatniego elementu w pythonie jest

>>> list[-1:] # returns indexed value
    [3]
>>> list[-1]  # returns value
    3

istnieje wiele innych metod osiągnięcia tego celu, ale są one krótkie i słodkie w użyciu.


2
jeśli twoja długość listy wynosi zero, to rozwiązanie działa, dopóki list[-1]wystąpi błąd.
anon01

Co? Dlaczego miałby to zrobić a[-1:][0] w ogóle ? On i a[-1]tak zapewnia . Wyjaśnienie proszę?
kaboom

51

Jak uzyskać w Pythonie ostatni element listy?

Aby zdobyć ostatni element,

  • bez zmiany listy oraz
  • zakładając, że wiesz, że lista ma ostatni element (tzn. jest niepusty)

przejdź -1do notacji indeksu dolnego:

>>> a_list = ['zero', 'one', 'two', 'three']
>>> a_list[-1]
'three'

Wyjaśnienie

Indeksy i wycinki mogą przyjmować jako argumenty ujemne liczby całkowite.

Mam zmodyfikowany przykład z dokumentacji , aby wskazać, który element w sekwencji każdego indeksu odniesienia, w tym przypadku, w ciągu "Python", -1odwołuje się do ostatniego elementu, postać, 'n':

 +---+---+---+---+---+---+
 | P | y | t | h | o | n |
 +---+---+---+---+---+---+
   0   1   2   3   4   5 
  -6  -5  -4  -3  -2  -1

>>> p = 'Python'
>>> p[-1]
'n'

Przypisanie poprzez iterowalne rozpakowywanie

Ta metoda może niepotrzebnie zmaterializować drugą listę w celu uzyskania ostatniego elementu, ale ze względu na kompletność (i ponieważ obsługuje każdą iterowalną - nie tylko listy):

>>> *head, last = a_list
>>> last
'three'

Nazwa zmiennej head jest powiązana z niepotrzebną nowo utworzoną listą:

>>> head
['zero', 'one', 'two']

Jeśli nie zamierzasz nic robić z tą listą, będzie to więcej apropos:

*_, last = a_list

Lub, naprawdę, jeśli wiesz, że jest to lista (lub przynajmniej akceptuje notację indeksu dolnego):

last = a_list[-1]

W funkcji

Komentator powiedział:

Chciałbym, żeby Python miał funkcję first () i last (), tak jak Lisp ... pozbyłby się wielu niepotrzebnych funkcji lambda.

Można by je dość łatwo zdefiniować:

def last(a_list):
    return a_list[-1]

def first(a_list):
    return a_list[0]

Lub użyj operator.itemgetter:

>>> import operator
>>> last = operator.itemgetter(-1)
>>> first = operator.itemgetter(0)

W obu przypadkach:

>>> last(a_list)
'three'
>>> first(a_list)
'zero'

Przypadki specjalne

Jeśli robisz coś bardziej skomplikowanego, może okazać się, że bardziej wydajne jest uzyskanie ostatniego elementu na nieco inne sposoby.

Jeśli dopiero zaczynasz programować, powinieneś unikać tej sekcji, ponieważ łączy ona semantycznie różne części algorytmów razem. Zmiana algorytmu w jednym miejscu może mieć niezamierzony wpływ na inną linię kodu.

Staram się zapewnić zastrzeżenia i warunki tak dokładnie, jak potrafię, ale być może coś mi umknęło. Proszę o komentarz, jeśli uważasz, że zostawiam zastrzeżenie.

Krajanie na plastry

Fragment listy zwraca nową listę - dzięki czemu możemy wyciąć od -1 do końca, jeśli chcemy, aby element był na nowej liście:

>>> a_slice = a_list[-1:]
>>> a_slice
['three']

Ma to tę zaletę, że nie zawiedzie, jeśli lista jest pusta:

>>> empty_list = []
>>> tail = empty_list[-1:]
>>> if tail:
...     do_something(tail)

Podczas gdy próba dostępu za pomocą indeksu rodzi problem, z IndexErrorktórym należałoby się uporać:

>>> empty_list[-1]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list index out of range

Ale ponownie, krojenie w tym celu powinno być wykonane tylko wtedy, gdy potrzebujesz:

  • utworzono nową listę
  • a nowa lista będzie pusta, jeśli poprzednia lista była pusta.

for pętle

W Pythonie nie ma wewnętrznego zakresu w for pętli.

Jeśli wykonujesz już pełną iterację na liście, do ostatniego elementu nadal będzie odwoływać się nazwa zmiennej przypisana w pętli:

>>> def do_something(arg): pass
>>> for item in a_list:
...     do_something(item)
...     
>>> item
'three'

To nie jest semantycznie ostatnia rzecz na liście. Jest to semantycznie ostatnia rzecz, z którą nazwa itembyła związana.

>>> def do_something(arg): raise Exception
>>> for item in a_list:
...     do_something(item)
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "<stdin>", line 1, in do_something
Exception
>>> item
'zero'

Dlatego należy tego użyć tylko do uzyskania ostatniego elementu

  • już zapętlają się, i
  • wiesz, że pętla zakończy się (nie zepsuje się lub nie wyjdzie z powodu błędów), w przeciwnym razie wskaże ostatni element, do którego odwołuje się pętla.

Pobieranie i usuwanie

Możemy również mutować naszą oryginalną listę, usuwając i zwracając ostatni element:

>>> a_list.pop(-1)
'three'
>>> a_list
['zero', 'one', 'two']

Ale teraz oryginalna lista została zmodyfikowana.

(w -1rzeczywistości jest domyślnym argumentem, więc list.popmożna go używać bez argumentu indeksu):

>>> a_list.pop()
'two'

Zrób to tylko, jeśli

  • wiesz, że lista zawiera elementy lub jesteś przygotowany do obsługi wyjątku, jeśli jest pusty, i
  • zamierzasz usunąć ostatni element z listy, traktując go jak stos.

Są to ważne przypadki użycia, ale niezbyt częste.

Zapisywanie reszty na później:

Nie wiem, dlaczego to zrobiłeś, ale dla kompletności, ponieważ reversedzwraca iterator (który obsługuje protokół iteratora), możesz przekazać jego wynik do next:

>>> next(reversed([1,2,3]))
3

To jest jak odwrócenie tego:

>>> next(iter([1,2,3]))
1

Ale nie mogę wymyślić dobrego powodu, aby to zrobić, chyba że później będziesz potrzebować reszty odwrotnego iteratora, który prawdopodobnie wyglądałby bardziej tak:

reverse_iterator = reversed([1,2,3])
last_element = next(reverse_iterator)

use_later = list(reverse_iterator)

i teraz:

>>> use_later
[2, 1]
>>> last_element
3

13

Aby temu zapobiec IndexError: list index out of range, użyj tej składni:

mylist = [1, 2, 3, 4]

# With None as default value:
value = mylist and mylist[-1]

# With specified default value (option 1):
value = mylist and mylist[-1] or 'default'

# With specified default value (option 2):
value = mylist[-1] if mylist else 'default'


10

lst[-1]jest najlepszym podejściem, ale przy ogólnych iteracjach rozważ more_itertools.last:

Kod

import more_itertools as mit


mit.last([0, 1, 2, 3])
# 3

mit.last(iter([1, 2, 3]))
# 3

mit.last([], "some default")
# 'some default'

6

list[-1]pobierze ostatni element listy bez zmiany listy. list.pop()pobierze ostatni element listy, ale zmutuje / zmieni oryginalną listę. Zwykle mutowanie oryginalnej listy nie jest zalecane.

Alternatywnie, jeśli z jakiegoś powodu szukasz czegoś mniej pytonicznego, możesz użyć list[len(list)-1], zakładając, że lista nie jest pusta.


2
Prawdopodobnie źle jest założyć, że mutowanie oryginalnej listy zwykle nie jest zalecane, ponieważ w końcu jest to bardzo często przeprowadzane
Aaron,

6

Możesz również użyć poniższego kodu, jeśli nie chcesz otrzymywać IndexError, gdy lista jest pusta.

next(reversed(some_list), None)

4

Ok, ale co z pospolitym w prawie każdym języku items[len(items) - 1]? Jest to IMO najłatwiejszy sposób na uzyskanie ostatniego elementu, ponieważ nie wymaga on żadnej wiedzy pythońskiej .


3
items [len (items) - 1] jest zasadniczo tym, co Python robi pod maską, ale ponieważ długość sekwencji jest już zapisana w sekwencji, nie trzeba go liczyć, tworzysz więcej pracy, niż to konieczne.
Dan Gayle,

21
skoro piszesz Python, naprawdę powinieneś postarać się być bardziej Pythonic
Michael Wu

5
@MichaelWu Nie ma sensu tego robić. Sposób w Pythonie często nie jest oczywisty, wymaga więcej uwagi, gdy musisz wprowadzić nowe osoby do projektu i, oczywiście, nie zadziała, gdy będziesz musiał przejść na inne języki, takie jak Java - nie możesz używać wiedzy specyficznej dla Pythona. Jeśli pominiesz sposób pythonowy, jak to możliwe, powrót do projektu po miesiącach / latach jest znacznie łatwiejszy.
Radek Anuszewski

7
@Pneumokok Masz rację, ale argumentowałbym, że indeksowanie list jest bardzo podstawową techniką Pythona w porównaniu do generatorów powiedzmy. Ponadto, po co zawracać sobie głowę używaniem innego niż C lub javascript, jeśli nie zamierzasz korzystać z indywidualnych narzędzi językowych i składni? Dzięki temu możesz konsekwentnie robić wszystko na wszystkie sposoby.
Matthew Purdon,

Chociaż nie jest zbyt pytoniczny, myślę, że pod pewnymi względami jest to lepsze niż some_list[-1]podejście, ponieważ jest bardziej logiczne i pokazuje, co tak naprawdę robi lepiej niż some_list[-1]moim zdaniem.
Byron Filer
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.