964 votes

Traverser une liste en ordre inverse en Python

Je peux donc commencer par collection[len(collection)-1] et se terminent par collection[0] .

Je veux aussi pouvoir accéder à l'index de la boucle.

1586voto

Greg Hewgill Points 356191

Utilisez la fonction intégrée reversed() fonction :

>>> a = ["foo", "bar", "baz"]
>>> for i in reversed(a):
...     print(i)
... 
baz
bar
foo

Pour accéder également à l'index original, utilisez enumerate() sur votre liste avant de la transmettre à reversed() :

>>> for i, e in reversed(list(enumerate(a))):
...     print(i, e)
... 
2 baz
1 bar
0 foo

Depuis enumerate() retourne un générateur et les générateurs ne peuvent pas être inversés, vous devez le convertir en un list d'abord.

1 votes

Merci. Par curiosité, cette méthode inversée crée-t-elle une copie séparée de la collection ou modifie-t-elle simplement le bouclage ?

173 votes

Aucune copie n'est créée, les éléments sont inversés à la volée pendant la traversée ! C'est une caractéristique importante de toutes ces fonctions d'itération (qui se terminent toutes par "ed").

0 votes

La fonction reversed() fait une copie de la collection. Pour modifier une liste existante, utilisez la méthode .reverse().

231voto

mipadi Points 135410

Vous pouvez le faire :

for item in my_list[::-1]:
    print item

(Ou tout ce que vous voulez faire dans la boucle for).

Le site [::-1] slice inverse la liste dans la boucle for (mais ne modifie pas réellement votre liste de façon "permanente").

34 votes

[::-1] crée une copie superficielle, donc elle ne modifie pas le tableau, ni de manière "permanente" ni de manière "temporaire".

6 votes

Cette méthode est légèrement plus lente que l'utilisation de l'inversion, du moins sous Python 2.7 (testé).

21 votes

Comment fonctionne cette réponse : il crée une copie découpée de la liste avec les paramètres : point de départ : non spécifié (devient la longueur de la liste et commence donc à la fin), point final : non spécifié (devient un nombre magique autre que 0 probablement -1 donc se termine au début) et étape : -1 (itère en arrière dans la liste, 1 à la fois).

107voto

Alan Rowarth Points 451

Cela peut se faire de la manière suivante :

for i in range(len(collection)-1, -1, -1):
    print collection[i]

    # print(collection[i]) for python 3. +

Donc ton estimation était assez proche :) C'est un peu bizarre, mais ça revient à dire : commencez par 1 de moins que len(collection) et continuez jusqu'à ce que vous arriviez juste avant -1, par pas de -1.

Fyi, le help est très utile car elle vous permet de consulter la documentation d'un élément à partir de la console Python, par exemple :

help(range)

1 votes

Pour les versions de Python antérieures à 3.0, je pense que xrange est préférable à range pour les grands len(collection).

0 votes

Je pense que vous avez raison :) il me semble que range() génère toute la plage sous forme de tableau, mais xrange() renvoie un itérateur qui ne génère les valeurs que lorsqu'elles sont nécessaires.

18 votes

Ça a l'air trop bizarre avec tant de -1 's. Je dirais juste reversed(xrange(len(collection)))

77voto

Triptych Points 70247

Si vous avez besoin de l'index de la boucle, et que vous ne voulez pas parcourir la liste entière deux fois, ou utiliser de la mémoire supplémentaire, j'écrirais un générateur.

def reverse_enum(L):
   for index in reversed(xrange(len(L))):
      yield index, L[index]

L = ['foo', 'bar', 'bas']
for index, item in reverse_enum(L):
   print index, item

3 votes

J'appellerais la fonction enumerate_reversed, mais ce n'est peut-être que mon goût. Je pense que votre réponse est la plus propre pour la question spécifique.

1 votes

reversed(xrange(len(L))) produit les mêmes indices que xrange(len(L)-1, -1, -1) .

0 votes

@JF - oui, à l'époque je pensais avoir une raison de ne pas le faire de cette façon, mais maintenant je ne m'en souviens plus. Je le change maintenant.

36voto

tzot Points 32224

Le site reversed La fonction intégrée est pratique :

for item in reversed(sequence):

Le site documentation pour inversé explique ses limites.

Pour les cas où je dois parcourir une séquence en sens inverse avec l'index (par exemple pour des modifications en place qui changent la longueur de la séquence), j'ai défini cette fonction dans mon module codeutil :

from six.moves import zip as izip, range as xrange

def reversed_enumerate(sequence):
    return izip(
        reversed(xrange(len(sequence))),
        reversed(sequence),
    )

Celui-ci évite de créer une copie de la séquence. Évidemment, le reversed les limitations s'appliquent toujours.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X