2009-06-10 7 views
3

J'ai une liste d'éléments (qui sont des lignes de table HTML, extraites avec de belles soupe) et je dois parcourir la liste et obtenir des éléments pairs et impairs (je veux dire index) pour chaque boucle s'exécute. Mon code ressemble à ceci:itérer simultanément par paires et objets les plus bizarres de la liste

for top, bottom in izip(table[::2], table[1::2]): 
    #do something with top 
    #do something else with bottom 

Comment rendre ce code moins laid? Ou peut-être est-ce un bon moyen de le faire?

EDIT:

table[1::2], table[::2] => table[::2], table[1::2] 

Répondre

4

Essayez:

def alternate(i): 
    i = iter(i) 
    while True: 
     yield(i.next(), i.next()) 

>>> list(alternate(range(10))) 
[(0, 1), (2, 3), (4, 5), (6, 7), (8, 9)] 

Cette solution fonctionne sur une séquence, pas de listes juste, et ne copie pas la séquence (il sera beaucoup plus efficace si vous ne voulez que les premiers éléments d'une longue séquence).

+0

O vraiment aimé cette solution, merci! – uolot

+0

Argh, pourquoi je ne peux pas éditer le commentaire? Devrait être "j'aime vraiment ..." – uolot

0

semble bon. Ma seule suggestion serait d'envelopper dans une fonction ou une méthode. De cette façon, vous pouvez lui donner un nom (evenOddIter()) qui le rend beaucoup plus lisible.

+0

Quelle est la différence entre la fonction et la méthode dans ce contexte? –

+0

Cela dépend si le code ci-dessus fait partie d'une classe ou d'un niveau supérieur. Si c'est dans une classe qui obtient beaucoup de réutilisation, il peut être logique d'utiliser une méthode. Lorsque vous utilisez une fonction, il serait plus simple de la réutiliser en dehors de toute classe, mais cela encombrerait l'espace de noms global. –

+0

c'est dans une classe, mais cette boucle n'est exécutée que dans un seul endroit, donc je pense qu'il est nécessaire d'en faire une méthode. merci quand même – uolot

5

izip est une option assez bonne, mais voici quelques solutions de rechange puisque vous n'êtes pas satisfait avec elle:

>>> def chunker(seq, size): 
...  return (tuple(seq[pos:pos+size]) for pos in xrange(0, len(seq), size)) 
... 
>>> x = range(11) 
>>> x 
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 
>>> chunker(x, 2) 
<generator object <genexpr> at 0x00B44328> 
>>> list(chunker(x, 2)) 
[(0, 1), (2, 3), (4, 5), (6, 7), (8, 9), (10,)] 
>>> list(izip(x[1::2], x[::2])) 
[(1, 0), (3, 2), (5, 4), (7, 6), (9, 8)] 

Comme vous pouvez le voir, cela a l'avantage de traiter correctement une quantité inégale des éléments qui peut ou ne pas être important pour vous. Il y a aussi cette recette de la itertools documentation itself:

>>> def grouper(n, iterable, fillvalue=None): 
...  "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx" 
...  args = [iter(iterable)] * n 
...  return izip_longest(fillvalue=fillvalue, *args) 
... 
>>> 
>>> from itertools import izip_longest 
>>> list(grouper(2, x)) 
[(0, 1), (2, 3), (4, 5), (6, 7), (8, 9), (10, None)] 
+0

Merci - les deux recettes semblent bonnes. En tout cas j'ai demandé parce que je m'intéressais quelles sont les autres façons de le faire (et d'apprendre plus de Python - et je l'ai fait :)) – uolot