Quel est le moyen le plus efficace d'alterner de prendre des valeurs de différents itérateurs en python, de sorte que, par exemple, mais existe-t-il une manière plus efficace ou plus propre? (Ou, mieux encore, un alternatif (xrange (1, 7, 2), xrange (2, 8, 2)) Code> donnerait 1, 2, 3, 4, 5, 6. Je sais qu'un moyen de mettre en œuvre ce serait:
iTertools code> fonction que j'ai manqué?) P> p>
6 Réponses :
Qu'en est-il de Zip? Vous pouvez également essayer Izip de izip de iTertools si ce n'est pas ce que vous voulez, veuillez donner plus d'exemples dans votre post de question. P> P>
Seul, Izip ne suffit pas à mes besoins. Mais mettre une chaîne autour d'izip, comme chaîne.from_iterable (izip (itérables)) code> fonctionne. Je suppose que c'est la chose cool sur les ittérables. Merci!
Le problème avec zip code> dans ce cas est qu'il évaluera immédiatement les itérateurs, vous obligeant à renverser la sémantique génératrice.
Ce qui serait particulièrement problématique envisageant que mon étui d'utilisation initial pour cela était des itérateurs qui ont généré un nombre infini de valeurs.
Vous pouvez définir alterner code> comme ceci:
Dummy=object()
def alternate(*iters):
for elt in itertools.chain.from_iterable(
itertools.izip_longest(*iters,fillvalue=Dummy)):
if elt is not Dummy:
yield elt
Pourrait être plus propre pour définir mannequin comme dummy = objet () code>
@Chris: Merci! J'ai fait le changement.
pour une implémentation "propre", vous voulez mais peut-être que vous voulez p>
Est-ce que cela épuise le générateur avant de le transmettre à Izip puis à la chaîne?
@Dan si iters code> était un générateur, il l'épuiserait, au moins dans Python 2; Exécution
def z (* iters): Imprimer (type (iters)); Imprimer (iters) code> puis
z (* (i pour i in xrange (1,18))) code> impression
S'ils sont la même longueur, ITERTOOL.IFIP peut être levé comme suit:
def alternate(*iters): for row in itertools.izip(*iters): for i in row: yield i
voir tourbrobin code> dans le
itTools Section "Recettes"
. C'est une version plus générale de remplaçante. def roundrobin(*iterables):
"roundrobin('ABC', 'D', 'EF') --> A D E B F C"
# Recipe credited to George Sakkis
pending = len(iterables)
nexts = cycle(iter(it).__next__ for it in iterables)
while pending:
try:
for next in nexts:
yield next()
except StopIteration:
pending -= 1
nexts = cycle(islice(nexts, pending))
Il y a deux problèmes avec votre tentative:
iters code> avec iTER () code> de sorte qu'il échouera avec itérables tels que la liste code>; et li>
- par
passe code> ing sur stopiteration code> Votre générateur est une boucle infinie. Li>
ol> Un code simple qui résout ces deux problèmes et reste facile à lire et à comprendre: p> xxx pré> p>
Voulez-vous dire 1, 2, 7, 8, 2, 2?
Question très similaire: Stackoverflow.com / Questions / 243865 / ...
@San Devlin: Non, 1 2 3 4 5 6 est correct. docs.python.org/library/functions.html#xrange