Comment parcourir tout sauf le dernier élément d'une liste?

160

Je voudrais parcourir une liste en vérifiant chaque élément par rapport à celui qui le suit.

Existe-t-il un moyen de parcourir tout sauf le dernier élément en utilisant for x in y? Je préférerais le faire sans utiliser d'index si je le peux.

Remarque

freespace a répondu à ma question, c'est pourquoi j'ai accepté la réponse, mais SilentGhost a répondu à la question que j'aurais dû poser.

Toutes mes excuses pour la confusion.

David Sykes
la source

Réponses:

316
for x in y[:-1]

S'il ys'agit d'un générateur, alors ce qui précède ne fonctionnera pas.

espace libre
la source
Cela répond à ma question, merci, mais j'ai oublié de demander comment j'obtiendrais l'article après x. Est-ce possible?
David Sykes
3
- 1 Je ne pense pas que cela réponde à la question. Il ne s'agit pas de comparer chaque élément avec le suivant. - odwl il y a 0 secondes
odwl
4
Je pense que je l'ai fait. L'auteur a dit qu'il aimerait faire X, puis a demandé comment il pouvait faire Y. J'ai répondu comment il pouvait faire Y. Qu'il ait accepté ma réponse indiquerait que j'ai répondu à la question qu'il a posée, sinon à la question qu'il voulait vraiment poser. Le demandeur est invité à rétrograder cette réponse.
freespace
7
Ce n'est pas parce que le PO aurait dû poser une autre question dans la première, que sa question et cette réponse ne sont pas très utiles aux autres. +1
Prof.Falken
1
Vous dites que cela ne fonctionne pas pour les générateurs. Quelle est l'alternative quand yest un générateur?
Joost
50

le moyen le plus simple de comparer l'élément de séquence avec ce qui suit:

for i, j in zip(a, a[1:]):
     # compare i (the current) to j (the following)
SilentGhost
la source
15
Cela répond à la question que j'aurais aimé poser. Merci
David Sykes
3
En fait, vous pouvez omettre la première tranche, car zip tronque la liste la plus longue à la longueur de la plus courte. Cela vous évitera une création de liste. (Juste au cas où vous auriez affaire à d'énormes listes. Mais dans ce cas, vous devriez suivre l'approche d'Ants Aasma, qui ne copie rien.)
bayer
19

Si vous souhaitez obtenir tous les éléments de la séquence par paire, utilisez cette approche (la fonction par paire provient des exemples du module itertools).

from itertools import tee, izip, chain

def pairwise(seq):
    a,b = tee(seq)
    b.next()
    return izip(a,b)

for current_item, next_item in pairwise(y):
    if compare(current_item, next_item):
        # do what you have to do

Si vous avez besoin de comparer la dernière valeur à une valeur spéciale, chaînez cette valeur jusqu'à la fin

for current, next_item in pairwise(chain(y, [None])):
Fourmis Aasma
la source
veuillez noter que l'utilisation de next pour les ombres de nom de variable intégrées
SilentGhost
1
Personnellement, cela ne me dérange pas d'observer les fonctions intégrées moins utilisées lorsque la portée de la variable est petite et que le nom est bon pour la lisibilité. Néanmoins, édité les noms des variables pour maintenir de bonnes pratiques de codage.
Ants Aasma
5

si vous vouliez comparer le nième élément avec le n + 1 ème élément de la liste, vous pourriez aussi faire avec

>>> for i in range(len(list[:-1])):
...     print list[i]>list[i+1]

notez qu'il n'y a pas de codage en dur là-bas. Cela devrait être correct, sauf si vous ressentez le contraire.

Perpetualcoder
la source
3
Vous pouvez remplacer len (liste [: - 1]) par len (liste) - 1 pour éviter une copie de liste. Et évitez d'utiliser une variable appelée list ...
Remy Blank
2

Pour comparer chaque élément avec le suivant dans un itérateur sans instancier une liste:

import itertools
it = (x for x in range(10))
data1, data2 = itertools.tee(it)
data2.next()
for a, b in itertools.izip(data1, data2):
  print a, b
odwl
la source
2
c'est exactement ce qui a été suggéré par Ants Aasma stackoverflow.com/questions/914715/…
SilentGhost
1

Cela répond à ce que l'OP aurait dû demander , c'est-à-dire parcourir une liste comparant des éléments consécutifs (excellente réponse SilentGhost ), mais généralisée pour tout groupe ( n-gramme ): 2, 3, ... n:

zip(*(l[start:] for start in range(0, n)))

Exemples:

l = range(0, 4)  # [0, 1, 2, 3]

list(zip(*(l[start:] for start in range(0, 2)))) # == [(0, 1), (1, 2), (2, 3)]
list(zip(*(l[start:] for start in range(0, 3)))) # == [(0, 1, 2), (1, 2, 3)]
list(zip(*(l[start:] for start in range(0, 4)))) # == [(0, 1, 2, 3)]
list(zip(*(l[start:] for start in range(0, 5)))) # == []

Explications:

  • l[start:] génère une liste / générateur à partir de l'index start
  • *listou *generator: passe tous les éléments à la fonction englobante zipcomme si elle avait été écritezip(elem1, elem2, ...)

Remarque:

AFAIK, ce code est aussi paresseux que possible. Pas testé.

juanmirocks
la source