Quel est le moyen le plus efficace de faire quelque chose comme ce code C

for(int i = 0; i < 10; i++) {
    printf("%d\n", i);
    if(i == 5)
        i = 1;
}

En python, donc la sortie serait

0
1
2
3
4
5
1
2
3
4
5
1

Je sais qu'il y en a pour à côté de ()

iterator = iter(range(0, 10))
for i in iterator:
    next(iterator)
    print(i)

Donc ce code imprimerait chaque deuxième nombre, mais je ne sais pas comment revenir en arrière pour la boucle.

0
Tomas Lapsansky 13 avril 2018 à 17:47

4 réponses

Meilleure réponse

Donc je me rends compte des commentaires que je dois utiliser en boucle tout comme ça

i = 0
while i < 10:
    print(i)
    if i == 5:
        i = 1

L'exemple ci-dessus avec itertools et chain est sympa, mais je voulais une solution comme celle-ci pendant le cycle, mais je ne pensais pas à while. Dans mon code, il y a des conditions plus complexes, non seulement cette "chaîne" facile, mais je pensais que cela suffirait pour une démonstration de "saut".

1
Tomas Lapsansky 13 avril 2018 à 15:07

Vous pouvez boucler pour toujours en utilisant itertools.cycle() et vous pouvez utilisez itertools.chain() pour ajouter la condition de départ comme:

import itertools as it
for i in it.chain((0,), it.cycle(range(1, 6))):
    print(i)

Résultats:

0
1
2
3
4
5
1
2
3
4
5
7
Stephen Rauch 13 avril 2018 à 14:54

Vous pouvez reproduire une grande partie du style C pour la boucle à l'aide d'une classe itérateur.

Par exemple:

class cFor:   
    def __init__(self,start,condition,step=1):
        self.index     = start
        self.nextIndex = start
        self.doLoop    = condition
        if type(condition) == type(start):
            self.doLoop  = lambda x:x < condition
        self.getNext   = step
        if type(step) == type(start):
            self.getNext = lambda x:x + step

    def __iter__(self):
        return self

    def next(self) : return self.__next__()

    def __next__(self):
        if self.doLoop(self.nextIndex):
            self.index     = self.nextIndex
            self.nextIndex = self.getNext(self.index)
            return self.index
        raise StopIteration()

Cela vous permettra d'effectuer des boucles simples:

for i in cFor(0,10,2) : print(i)
# 0, 2, 4, 6, 8

Et, à l'aide de lambdas, vous pouvez fournir votre propre calcul de condition et d'incrémentation:

for i in cFor(1, lambda i:i<=10, lambda i:i+3): print(i)
# 1, 4, 7, 10

Ou appliquez des calculs "en ligne" plus complexes:

[ a for a,b in cFor((1,1),lambda ab:ab[1]<30,lambda ab:(ab[1],sum(ab))) ]
# [ 1, 1, 2, 3, 5, 8, 13 ]

Pour pouvoir modifier l'index (ou la condition ou l'incrément) dans la boucle, vous pouvez créer une fonction de générateur qui renvoie à la fois l'index en cours et l'instance de l'itérateur. Cela vous permettra de prendre le contrôle des propriétés de l'itérateur dans le corps de la boucle.

def cForLoop(start,condition,step=1):
    loop = cFor(start,condition,step)
    while True : yield loop.next(), loop

for i,loop in cForLoop(0,10):
    print(i)
    if i == 5 : loop.nextIndex = 1
# 0, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, ....

Vous pouvez, par exemple, l'utiliser pour implémenter un simple tri à bulles:

arr = [3,7,4,2,8,1,6]

for i,loop in cForLoop(1,len(arr)):
    if arr[i-1] > arr[i] :
        arr[i],arr[i-1] = arr[i-1],arr[i]
        loop.nextIndex = max(1,i-1) 

# arr == [1, 2, 3, 4, 6, 7, 8]
0
Alain T. 14 avril 2018 à 23:23

@Stephen J'essaye sans chaîne et je travaille bien. merci gentil code

import itertools as it
for i in it.cycle(range(1, 6)):
    print(i)
0
Caputo 13 avril 2018 à 15:01