Obtention du dernier élément d'une liste

2067

En Python, comment obtenez-vous le dernier élément d'une liste?

Janusz
la source

Réponses:

3110

some_list[-1] est le plus court et le plus Pythonic.

En fait, vous pouvez faire beaucoup plus avec cette syntaxe. La some_list[-n]syntaxe obtient le nième au dernier élément. Obtient donc some_list[-1]le dernier élément, some_list[-2]obtient l'avant-dernier, etc., jusqu'à some_list[-len(some_list)]ce qui vous donne le premier élément.

Vous pouvez également définir des éléments de liste de cette manière. Par exemple:

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

Notez que l'obtention d'un élément de liste par index soulèvera un IndexErrorélément si l'élément attendu n'existe pas. Cela signifie que some_list[-1]déclenchera une exception si some_listest vide, car une liste vide ne peut pas avoir de dernier élément.

Sasha Chedygov
la source
6
Quelque chose me manque some_list.last- ce serait une belle ligne de code
Dmitry P.
257

Si vos objets str()ou list()peuvent finir par être vides comme ceci: astr = ''ou alist = [], alors vous voudrez peut-être utiliser à la alist[-1:]place de l' alist[-1]objet "similitude".

La signification de ceci est:

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

Là où la distinction est faite, le retour d'un objet de liste vide ou d'un objet str vide est plus un "dernier élément" que un objet d'exception.

DevPlayer
la source
26
Voté parce que je pense que le cœur de cette réponse est incorrect. L'obtention d'une liste lorsque vous voulez un élément ne fait que reporter l'inévitable "index de liste hors de portée" - et c'est ce qui devrait se produire lorsque vous tentez d'obtenir un élément d'une liste vide. Pour les chaînes, astr [-1:] pourrait être une approche valide car elle renvoie le même type que astr [-1], mais je ne pense pas que le «:» aide à gérer les listes vides (et la question concerne les listes) . Si l'idée est d'utiliser "alist [-1:]" comme conditionnel au lieu de "len (alist)> 0", je pense qu'il est beaucoup plus lisible d'utiliser le dernier. (heureux de voter si j'ai raté quelque chose)
Stan Kurdziel
9
Votre vote négatif est compréhensible et valide. Cependant, je trouve qu'il y a deux camps de base sur quels objets d'exception sont destinés. Une certitude est que les exceptions interrompent votre application. Un camp utilise des exceptions dans les clauses try car l'autre camp utiliserait la structure if len (alist)> 0: à la place. Dans tous les cas, les exceptions sont des objets qui arrêtent votre code. Et en tant que tels pour moi, il y a moins d'objets de séquence comme des séquences "nulles" renvoyées qui n'arrêtent pas votre code. Ma préférence est d'utiliser des clauses IF pour tester des objets "null" au lieu d'objets qui arrêtent mon code que je devance avec une clause try.
DevPlayer
6
Voté parce que la syntaxe des tranches vaut la peine d'être discutée, mais je suis d'accord avec @StanKurdziel que la morphologie est incorrecte, vous déplacez simplement le poteau de but - j'ai trouvé que ma propre solution était liée à l'utilisation principale de 'ajoutez ceci à la liste si vous ne l'avez pas fait 'ne l'ajoutez pas déjà' (graphes à lignes delta), donc l'expression combinée if len(my_vector) == 0 or my_vector[-1] != update_valest un modèle réalisable. mais ce n'est certainement pas une solution globale - ce serait bien d'avoir une forme de syntaxe où None était le résultat
Mark Mullin
17
xs[-1] if xs else None
Gabriel
2
Pourquoi voudriez-vous «éviter» une IndexError? Si vous essayez d'indexer une liste ou une chaîne vide, vous obtiendrez une exception. Si vous voulez gérer cette exception, utilisez un try / except - c'est pour ça qu'il est là.
Chris Johnson
94

Vous pouvez également faire:

alist.pop()

Cela dépend de ce que vous voulez faire avec votre liste car la pop()méthode supprimera le dernier élément.

Taurus Olson
la source
71

La façon la plus simple d'afficher le dernier élément en python est

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

il existe de nombreuses autres méthodes pour atteindre un tel objectif, mais elles sont courtes et faciles à utiliser.

Atul Arvind
la source
2
si la longueur de votre liste est nulle, cette solution fonctionne pendant que list[-1]l'erreur se produit.
anon01
Quelle? Pourquoi voudriez - vous faire a[-1:][0] du tout ? Il fournit de a[-1]toute façon aussi. Explication s'il vous plait?
kaboom
52

En Python, comment obtenez-vous le dernier élément d'une liste?

Pour obtenir simplement le dernier élément,

  • sans modifier la liste, et
  • en supposant que vous savez que la liste a un dernier élément (c'est-à-dire qu'elle n'est pas vide)

passer -1à la notation en indice:

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

Explication

Les index et les tranches peuvent prendre des entiers négatifs comme arguments.

J'ai modifié un exemple de la documentation pour indiquer à quel élément d'une séquence chaque index fait référence, dans ce cas, dans la chaîne "Python", fait -1référence au dernier élément, le caractère 'n',:

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

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

Affectation via le déballage itérable

Cette méthode peut matérialiser inutilement une deuxième liste dans le seul but d'obtenir le dernier élément, mais dans un souci d'exhaustivité (et puisqu'elle prend en charge tout itérable - pas seulement les listes):

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

Le nom de la variable, head est lié à la liste nouvellement créée inutile:

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

Si vous avez l'intention de ne rien faire avec cette liste, ce serait plus approprié:

*_, last = a_list

Ou, vraiment, si vous savez que c'est une liste (ou du moins accepte la notation en indice):

last = a_list[-1]

Dans une fonction

Un intervenant a déclaré:

J'aimerais que Python ait une fonction pour first () et last () comme Lisp le fait ... il se débarrasserait de beaucoup de fonctions lambda inutiles.

Ceux-ci seraient assez simples à définir:

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

def first(a_list):
    return a_list[0]

Ou utilisez operator.itemgetter:

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

Dans tous les cas:

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

Cas spéciaux

Si vous faites quelque chose de plus compliqué, vous trouverez peut-être plus performant d'obtenir le dernier élément de manière légèrement différente.

Si vous êtes nouveau dans la programmation, vous devriez éviter cette section, car elle associe des parties d'algorithmes sémantiquement différentes. Si vous modifiez votre algorithme à un endroit, il peut avoir un impact involontaire sur une autre ligne de code.

J'essaie de fournir des mises en garde et des conditions aussi complètement que possible, mais j'ai peut-être manqué quelque chose. Veuillez commenter si vous pensez que je laisse une mise en garde.

Tranchage

Une tranche d'une liste renvoie une nouvelle liste - donc nous pouvons couper de -1 à la fin si nous voulons vouloir l'élément dans une nouvelle liste:

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

Cela a l'avantage de ne pas échouer si la liste est vide:

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

Alors que la tentative d'accès par index soulève un problème IndexErrorqui devrait être traité:

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

Mais encore une fois, le découpage à cette fin ne doit être effectué que si vous avez besoin:

  • une nouvelle liste créée
  • et la nouvelle liste doit être vide si la liste précédente était vide.

for boucles

En tant que fonctionnalité de Python, il n'y a pas de portée interne dans une forboucle.

Si vous effectuez déjà une itération complète sur la liste, le dernier élément sera toujours référencé par le nom de variable attribué dans la boucle:

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

Ce n'est pas sémantiquement la dernière chose de la liste. C'est sémantiquement la dernière chose à laquelle le nom itemétait lié.

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

Ainsi, cela ne devrait être utilisé pour obtenir le dernier élément que si vous

  • sont déjà en boucle, et
  • vous savez que la boucle se terminera (pas de rupture ou de sortie en raison d'erreurs), sinon elle pointera vers le dernier élément référencé par la boucle.

Obtention et suppression

Nous pouvons également muter notre liste d'origine en supprimant et en renvoyant le dernier élément:

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

Mais maintenant, la liste d'origine est modifiée.

( -1est en fait l'argument par défaut, il list.poppeut donc être utilisé sans argument d'index):

>>> a_list.pop()
'two'

Ne faites cela que si

  • vous savez que la liste contient des éléments ou êtes prêt à gérer l'exception si elle est vide, et
  • vous avez l'intention de supprimer le dernier élément de la liste, en le traitant comme une pile.

Ce sont des cas d'utilisation valides, mais pas très courants.

Sauvegarde du reste de l'inverse pour plus tard:

Je ne sais pas pourquoi vous le feriez, mais pour être complet, car reversedretourne un itérateur (qui prend en charge le protocole d'itérateur), vous pouvez transmettre son résultat à next:

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

C'est comme faire l'inverse:

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

Mais je ne peux pas penser à une bonne raison de le faire, sauf si vous aurez besoin du reste de l'itérateur inversé plus tard, qui ressemblerait probablement plus à ceci:

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

use_later = list(reverse_iterator)

et maintenant:

>>> use_later
[2, 1]
>>> last_element
3
Aaron Hall
la source
14

Pour éviter IndexError: list index out of range, utilisez cette syntaxe:

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'
Valentin Podkamennyi
la source
11

Une autre méthode:

some_list.reverse() 
some_list[0]
Sanjay Pradeep
la source
10

lst[-1]est la meilleure approche, mais avec des itérables généraux, considérez more_itertools.last:

Code

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'
pylang
la source
6

list[-1]récupérera le dernier élément de la liste sans modifier la liste. list.pop()récupérera le dernier élément de la liste, mais il mutera / modifiera la liste d'origine. Habituellement, la mutation de la liste d'origine n'est pas recommandée.

Alternativement, si, pour une raison quelconque, vous recherchez quelque chose de moins pythonique, vous pouvez utiliser list[len(list)-1], en supposant que la liste n'est pas vide.

Narcissique sondant
la source
2
Il est probablement mauvais de supposer que la mutation de la liste d'origine n'est généralement pas recommandée, car, après tout, elle est très couramment effectuée
Aaron
6

Vous pouvez également utiliser le code ci-dessous, si vous ne souhaitez pas obtenir IndexError lorsque la liste est vide.

next(reversed(some_list), None)
Yavuz Mester
la source
4

Ok, mais qu'en est-il de commun dans presque toutes les langues items[len(items) - 1]? C'est l'OMI le moyen le plus simple d'obtenir le dernier élément, car il ne nécessite aucune connaissance pythonique .

Radek Anuszewski
la source
3
items [len (items) - 1] est essentiellement ce que Python fait sous le capot, mais comme le len d'une séquence est déjà stocké dans la séquence, il n'est pas nécessaire de le compter, vous créez plus de travail que nécessaire.
Dan Gayle
21
puisque vous écrivez du Python, vous devriez vraiment essayer d'être plus Pythonique
Michael Wu
5
@MichaelWu Cela n'a aucun sens. La manière pythonique n'est souvent pas explicite, nécessite plus d'attention lorsque vous devez présenter de nouvelles personnes à projeter et, bien sûr, ne fonctionnerait pas lorsque vous devez passer à d'autres langages comme Java - vous ne pouvez pas utiliser des connaissances spécifiques à Python. Lorsque vous omettez la méthode pythonique autant que possible, il est beaucoup plus facile de revenir au projet après des mois / années.
Radek Anuszewski
7
@Pneumokok Vous le dites, mais je dirais que l'indexation de liste est une technique Python très basique par rapport aux générateurs. Aussi, pourquoi se donner la peine d'utiliser autre chose que C ou peut-être du javascript si vous n'allez pas profiter des outils et de la syntaxe de chaque langue? Ensuite, vous pouvez toujours tout faire à la dure dans tous vos projets.
Matthew Purdon du
Bien que ce ne soit pas très pythonique, je pense que c'est à certains égards mieux que l' some_list[-1]approche parce que c'est plus logique et montre ce qu'il fait réellement mieux qu'à some_list[-1]mon avis.
Byron Filer