Je pense que ** multiple for loop (nesting) ** est l'un des processus les plus évitables en programmation. Il y a environ un mois, l'article "Pourquoi évitons-nous obstinément pour" a été bourdonné et 2020/11/3 Avec plus de 1000 LGTM maintenant, beaucoup de gens ne veulent pas trop utiliser pour les boucles. Il existe plusieurs techniques en Python qui peuvent facilement éviter plusieurs boucles for, j'ai donc résumé celles que j'utilise le plus souvent. Si vous en avez d'autres, merci de nous le faire savoir dans les commentaires.
Je pense que chaque personne a différentes raisons (l'article ci-dessus traite également de divers détails), mais personnellement, il y a les deux points suivants.
À titre d'exemple de boucles for multiples, écrivons un programme qui recherche tous les 0 à 999 en tournant une instruction for de 0 à 9 dans chacun des 3 chiffres, et recherche un nombre égal ou supérieur à 500 et égal à zor. (adapté) Même une simple boucle triple pour vous fera rire.
mauvais exemple
result = []
for i in range(10):
for j in range(10):
for k in range(10):
summed = i*100+j*10+k
if i == j == k and summed >= 500:
result.append(summed)
print(result)
#Résultat d'exécution-> [555, 666, 777, 888, 999]
C'est toujours bon car le processus est simple, mais il devient vraiment difficile à lire quand cela devient plus compliqué.
Souvent, vous voulez sortir de toutes les boucles, pas seulement de la boucle la plus interne, une fois que vous remplissez certaines conditions. À titre d'exemple, écrivez un programme qui termine le processus lorsqu'il trouve ne serait-ce qu'un œil Zoro dans le processus de 1. ci-dessus. Lorsque je recherche "comment sortir de plusieurs boucles python" sur Google, bien qu'il existe une différence telle que ne pas utiliser de drapeau, cela s'écrit comme suit.
Il y a un mauvais exemple de pause
result = []
for i in range(10):
for j in range(10):
for k in range(10):
summed = i*100 + j*10 + k
if i == j == k and summed >= 500:
result.append(summed)
break
else:
continue
break
else:
continue
break
print(result)
#Résultat d'exécution-> [555]
C'est assez difficile à lire. Il est très difficile de dire où et où le retrait est le même. Si vous essayez d'écrire des processus plus compliqués, vous vous retrouverez avec un code que personne ne peut comprendre.
En utilisant itertools, vous pouvez générer des itérateurs qui produisent toutes les combinaisons et évitent plusieurs boucles for. De plus, comme c'est un itérateur qui est généré, même si vous faites toutes les combinaisons, il ne consommera pas beaucoup de mémoire. Si vous souhaitez lister toutes les combinaisons que vous avez créées, entourez simplement l'itérateur créé par la fonction intégrée list (). (Faites attention à la consommation de mémoire lors de la liste)
Quand j'écris le code qui sort de la boucle précédente en utilisant itertools,
Lors de l'utilisation d'itertools
import itertools
all_nums_iter = itertools.product(range(10),repeat=3)
result = []
for num in all_nums_iter:
summed = num[0]*100 + num[1]*10 + num[2]
if num[0] == num[1] and num[1] == num[2] and summed >= 500:
result.append(summed)
break
print(result)
#Résultat d'exécution-> [555]
Je pense que c'est plus facile à voir. À propos, itertools a une fonction qui peut non seulement énumérer tout, mais également énumérer des combinaisons et des séquences avec ou sans duplication.
Si vous utilisez déjà un tableau numpy, vous pouvez utiliser numpy.npindex pour éviter plusieurs boucles for. numpy.npindex transforme l'instruction for pour que toutes les valeurs du tableau reçu soient arrondies. Dans le code ci-dessous, options.shape est (10, 10, 10), donc i, j et k sont une recherche complète des instructions de 0 à 9 respectivement.
numpy.Lors de l'utilisation de npindex
import numpy as np
options = np.array([[[100*i+10*j+k for i in range(10)] for j in range(10)] for k in range(10)], dtype="int")
result = []
for i, j, k in np.ndindex(options.shape):
summed = options[i,j,k]
if i == j and j == k and summed >= 500:
result.append(summed)
break
print(result)
#Résultat d'exécution-> [555]
C'est assez rafraîchissant.
C'est un peu difficile et je pense que c'est utilisé dans un nombre limité de situations, mais vous pouvez également effectuer une recherche complète avec une fonction récursive. Si vous n'êtes pas familier avec les fonctions récursives, veuillez consulter "Quel genre de monde se développera si vous apprenez les fonctions récursives" dans la référence ci-dessous. Je pense que c'est assez facile à comprendre.
Lors de l'utilisation d'une fonction récursive
def dfs(depth, num):
if depth == 3:
num_str = str(num).zfill(3)
return num if num_str[0] == num_str[1] == num_str[2] and num >= 500 else None
for i in range(10):
ret = dfs(depth + 1, num + 10**(2-depth) * i)
if ret:
return ret
print(dfs(0, 0))
#Résultat d'exécution-> 555
Vous pouvez l'utiliser dans un nombre limité de situations, mais vous pouvez écrire du code intuitif et facile à comprendre dans des situations spécifiques (DFS: recherche de priorité en profondeur, etc.).
Pourquoi évitons-nous obstinément pour Méthode souvent utilisée dans la version python atcoder Quel genre de monde va s'étendre lorsque vous apprenez les fonctions récursives
Merci d'avoir lu jusqu'au bout. Simplifions les boucles for multiples difficiles à lire. Si vous connaissez un autre moyen facile d'écrire, veuillez me le faire savoir dans les commentaires. Si vous trouvez cet article utile, veuillez utiliser LGTM!
Recommended Posts