40 votes

Idiome Python "Every Other Element"

J'ai l'impression de passer beaucoup de temps à l'écriture de code en Python, mais pas assez de temps à la création Pythonic code. Récemment je suis tombé sur un drôle de petit problème que je pensais peut-être facile, idiomatiques solution. En paraphrasant l'origine, j'avais besoin de collecter tous les séquentielle paire dans une liste. Par exemple, pour la liste [1,2,3,4,5,6], je voulais calculer [(1,2),(3,4),(5,6)].

Je suis venu avec une solution rapide à l'époque qui ressemblait traduit Java. Revenant à la question, le mieux que je pouvais faire était de

l = [1,2,3,4,5,6]
[(l[2*x],l[2*x+1]) for x in range(len(l)/2)]

ce qui a aussi pour effet de jeter le dernier numéro dans le cas où la durée n'est pas la même.

Est-il plus idiomatiques approche que je suis absent, ou est-ce la meilleure je vais obtenir?

83voto

RichieHindle Points 98544

Cela le fera un peu plus soigneusement:

 >>> data = [1,2,3,4,5,6]
>>> zip(data[0::2], data[1::2])
[(1, 2), (3, 4), (5, 6)]
 

(mais il est sans doute moins lisible si vous n'êtes pas familier avec la fonction "foulée" des plages).

Comme votre code, il supprime la dernière valeur où vous avez un nombre impair de valeurs.

49voto

Celui souvent cité est:

 zip(*[iter(l)] * 2)
 

9voto

Mike Graham Points 22480

Pour cela, je copie généralement la recette grouper de la documentation itertools dans mon code.

 def grouper(n, iterable, fillvalue=None):
    "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    return izip_longest(fillvalue=fillvalue, *args)
 

9voto

Isaac Points 4557

Que diriez-vous d'utiliser la fonction de pas de range() :

 [(l[n],l[n+1]) for n in range(0,len(l),2)]
 

4voto

moshez Points 9516

La bonne chose n'est probablement pas de calculer des listes, mais d'écrire une fonction itérateur-> itérateur. C'est plus générique - cela fonctionne sur tous les itérables, et si vous voulez le "geler" dans une liste, vous pouvez utiliser la fonction "list ()".

 def groupElements(iterable, n):
    # For your case, you can hardcode n=2, but I wanted the general case here.
    # Also, you do not specify what to do if the 
    # length of the list is not divisible by 2
    # I chose here to drop such elements
    source = iter(iterable)
    while True:
        l = []
        for i in range(n):
            l.append(source.next())
        yield tuple(l)
 

Je suis surpris que le module itertools n'ait pas déjà de fonction pour cela - peut-être une future révision. D'ici là, n'hésitez pas à utiliser la version ci-dessus :)

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