web-dev-qa-db-fra.com

Comment rendre ce bloc de code python court et efficace

Je suis totalement novice en programmation et en python. Je résolvais un problème. J'ai trouvé la solution mais cela semble trop lent.

    if n % 2 == 0 and n % 3 == 0 and\
       n % 4 == 0 and n % 5 == 0 and\
       n % 6 == 0 and n % 7 == 0 and\
       n % 8 == 0 and n % 9 == 0 and\
       n % 10 == 0 and n % 11 == 0 and\
       n % 12 == 0 and n % 13 == 0 and\
       n % 14 == 0 and n % 15 == 0 and\
       n % 16 == 0 and n % 17 == 0 and\
       n % 18 == 0 and n % 19 == 0 and\
       n % 20 == 0:

C'est le code qui permet de vérifier si n est divisible par tous les nombres de 2 à 20 ou non.

Comment je peux le rendre court et efficace.

31
Sanatan Chaudhary

Il y a un compromis entre court et efficace.

Le Short way est if all(n % i == 0 for i in range(2, 21)):

La méthode Efficace indique que n % 20 == 0 signifie également que n % f == 0, où f est un facteur de 20. Par exemple, vous pouvez supprimer n % 2 == 0. Vous obtiendrez donc moins de comparaisons, ce qui vous permettra de courir plus vite. Ce faisant, vous remarquerez un motif et vous remarquerez que l’instruction entier se réduit à if n % 232792560 == 0! Mais cela a maintenant profondément intégré les 20, donc il sera difficile à décocher si vous avez besoin d’une limite supérieure différente.

Vous voyez donc que le chemin-efficace n'est pas si facile à lire et à maintenir. Choisissez donc celui qui convient le mieux à vos besoins.

79
Bathsheba
if all(n % i == 0 for i in range(2, 21)):

all accepte un itérable et retourne True si tous ses éléments sont évalués à True, False sinon. La partie n % i == 0 for i in range(2, 21) renvoie une valeur itérable avec 19 valeurs True ou False, selon que n est divisible par la valeur i correspondante.

49
DeepSpace

Construit dans tous aidera.

Renvoie True si tous les éléments de l'itérable sont vrais (ou si l'iterable est vide).

if all(n % i == 0 for i in xrange(2, 21))
6
Vishnu Upadhyay

Pour la variété, la façon dont vous auriez pu utiliser une boucle est la suivante:

test = True
for modulus in range(2, 21):
    if n % modulus != 0:
        test = False
        break
if test:
    # Do stuff

Si vous êtes à l'aise avec for-else, vous pouvez améliorer la concision en:

for modulus in range(2, 21):
    if n % modulus != 0:
        break
else:
    # Do stuff

bien que ce motif puisse être assez inhabituel pour que vous ne vouliez pas l’utiliser.

Une autre option consiste à écrire une fonction d'assistance

def is_divisible_by_integers_up_to(n, bound):
    for modulus in range(2, bound + 1):
        if n % modulus != 0:
            return False
    return True

if is_divisible_by_integers_up_to(n, 20):
    # Do stuff

Cependant, cet exemple particulier est assez simple pour que la meilleure solution consiste à utiliser all avec une expression génératrice telle que décrite dans les autres réponses.

4
Hurkyl

C'est juste une astuce mathématique, utilisez un objet comme n % "LCM(1,2,...,20) == 0 qui pourrait être codé comme

if n % 232792560 == 0:
    #do whatever you want
4
Masked Man

La plupart des exemples de code ci-dessus sont plus courts, mais (probablement) pas assez efficaces:

n%2 == 0 =>
    n%4 6 8... ==0
n%3 == 0 =>
    n%3 6 9... ==0

Nous ne pouvons utiliser que des nombres premiers pour vérifier dans la plage:

if all(n % i == 0 for i in [2,3,5,7,11,13,17,19])

De plus, si n divise le tout de 2 à 20, il divise le LCM de 2 à 20.

3
zinking

Vous avez besoin d'une condition qui évalue la valeur True lorsque toutes les divisions donnent un reste nul. Les deux solutions proposées jusqu'ici ne semblent pas le faire. Je soupçonne que la condition dont vous avez besoin est

if not any(n % i for i in range(2, 21)):
3
holdenweb

Similaire aux réponses précédentes:

import operator
x = 232792560
if reduce(operator.__and__, [x % n == 0 for n in xrange(2, 21, 2)]):
    print("ok")
2
copper.hat

Je suis moi-même un utilisateur très léger de python et je ne connaissais pas tout. Ces solutions sont plutôt chouettes (et probablement plus efficaces que celle que je vais publier). Mais si vous voulez voir une autre façon de procéder, voici une autre option:

def IsDivUpTo20(n):
   for i in range(2, 21):
      if n % i != 0:
         return False
   return True

Et appelez comme si

if IsDivUpTo20(50):
   #what to do if it is divisible
else:
   #what to do if it isn't
#for the example of 50, it'll be false and jump to the else part, but you can put any number of variable in there

Fonctionnellement, il fonctionne à peu près de la même façon que "tout", mais si vous n'êtes pas habitué à la syntaxe sophistiquée et aux fonctions intégrées, celui-ci est un peu plus intuitif.

* Note: J'utilise Python 3, pas Python 2.7 car la question est balisée. Je suis à peu près sûr que cela fonctionne dans cette version, mais si ce n'est pas le cas, s'il vous plaît, corrigez-moi.

2
Cody