J'ai un ensemble de quelques milliers de nombres premiers générés à partir d'un générateur:

primes = set(primegen()) = set([..., 89, 97, 101, 103, ...])

Certains de ces nombres premiers contiennent un zéro. Je voudrais m'en débarrasser. Y a-t-il un moyen de faire tout cela à la fois?

Actuellement, je supprime des éléments en parcourant les nombres premiers, avec une correspondance d'expression régulière:

import re
zero = re.compile('.+0.+') 

while primes:
    p = str(primes.pop())
    if zero.match(p):
        continue
    # do other stuff

Je pense que c'est la meilleure façon, mais je suis curieux de savoir si je me trompe.

4
ehacinom 9 mars 2016 à 00:01

5 réponses

Meilleure réponse

Résumer et synchroniser les réponses:

Avec les 100 000 premiers nombres premiers. (Utiliser timeit et copier les nombres premiers définis à chaque fois)

Racine

primes = {p for p in primes if '0' not in str(p)}

10 boucles, le meilleur des 3: 29,6 ms par boucle

Mike

while primes:
    p = str(primes.pop())
    if '0' in p:
        continue
    # do other stuff

10 boucles, le meilleur des 3: 38,9 ms par boucle

Garrett R

filter(lambda x: '0' not in str(x), primes)

1000 boucles, le meilleur des 3: 963 µs par boucle

Kasramvd

def zero_membership_checker(num):
    while num:
        if num%10 == 0:
            return True
        num = num / 10
    return False

1 boucles, le meilleur des 3: 6,65 s par boucle

Hiyume

import re
zero = re.compile('.+0.+') 

while primes:
    p = str(primes.pop())
    if zero.match(p):
        continue
    # do other stuff

10 boucles, le meilleur des 3: 69,4 ms par boucle

1
Mike 8 mars 2016 à 21:38

filter fonctionne également pour cette application:

In [25]: primes = set([83, 89, 97, 101, 103])

In [26]: filter(lambda x: '0' not in str(x), primes)
Out[26]: [89, 83, 97]

Voici quelques informations de timing, pour tous ceux qui sont curieux

In [37]: %timeit filter(lambda x: '0' not in str(x), myList)
10 loops, best of 3: 23.7 ms per loop

In [38]: %timeit {p for p in myList if '0' not in str(p)}
10 loops, best of 3: 22 ms per loop
1
Garrett R 8 mars 2016 à 21:36

Vous n'avez pas besoin de convertir les nombres en chaîne et d'utiliser l'expression régulière pour faire correspondre le zéro (ou mieux d'utiliser l'opérateur in pour la vérification de l'appartenance), ce qui est une opération coûteuse spécialement lorsque vous traitez des données volumineuses ensembles. Vous pouvez utiliser la fonction suivante pour détecter s'il y a un zéro dans votre numéro, puis l'utiliser dans une compréhension d'ensemble pour conserver les nombres attendus:

>>> def zero_membership_checker(num):
...     while num:
...         if num%10 == 0:
...             return True
...         num = num / 10
...     return False
... 
>>> s = set([89, 97, 101, 103])
>>> 
>>> {i for i in s if not zero_membership_checker(i)}
set([89, 97])
1
Kasramvd 8 mars 2016 à 21:07

Clause de non-responsabilité: je n'ai absolument aucune idée de ce que vous voulez en faire ou pourquoi cela serait utile. Je suppose simplement que vous souhaitez supprimer des nombres tels que 101 et 103 de votre ensemble primes car ils contiennent un chiffre zéro.

Vous n'avez même pas besoin d'expressions régulières pour cela. Cela peut se faire avec une simple compréhension de la liste:

# assume that primes is defined
str_primes = map(str, primes)
filtered_str_primes = [p for p in primes if "0" not in p]
filtered_primes = map(int, primes)

La réponse de Kasramvd pourrait être plus rapide, vous devriez tester les deux.

Je ne sais pas si votre ensemble n'est qu'un exemple ou si vous prévoyez d'utiliser un générateur pour produire une liste éventuellement infinie de nombres premiers. Dans ce dernier cas, vous pouvez utiliser itertools pour définir la séquence filtrée paresseusement (c'est-à-dire que ne générera l'élément suivant que lorsque vous le demanderez au lieu de consommer la liste entière):

from itertools import imap, ifilter
filtered_primes = imap(int,
                       ifilter(lambda p: "0" not in p,
                               imap(str, primes)))

Attendez, j'ai oublié, cela devrait produire le même résultat, mais avec moins de code (je vais laisser l'ancienne solution pour être complète):

filteres_primes = (p for p in primes if "0" not in str(p))
3
Community 23 mai 2017 à 12:07

Vous pouvez utiliser une compréhension d'ensemble pour filtrer votre ensemble existant de nombres premiers.

primes = {p for p in primes if '0' not in str(p)}
8
root 8 mars 2016 à 21:07