Le moyen le plus rapide et le plus élégant de vérifier si un élément exprimé par une expression régulière se trouve dans une liste donnée.
Par exemple: donné une liste:
'this' in newlist
Dans cette question: Expressions régulières: recherchez dans la liste
['this','thas']
donnez-moi une liste
list(filter(regex.match,newlist))
Cependant, je veux juste pour renvoyer Vrai ou Faux . Par conséquent, la méthode ci-dessus n'est pas efficace car elle examine tous les éléments de newlist. Existe-t-il un moyen comme
newlist = ['this','thiis','thas','sada']
regex = re.compile('th.s')
de vérifier efficacement et élégamment si un élément exprimé par une expression régulière est dans une liste donnée.
3 Réponses :
Comme Loocid l'a suggéré, vous pouvez utiliser n'importe quel . Je le ferais avec une expression de générateur comme celle-ci:
result = any(map(regex.match, newlist))
Voici une autre version avec map qui est légèrement plus rapide:
newlist = ['this','thiis','thas','sada']
regex = re.compile('th.s')
result = any(regex.match(word) for word in newlist)
print(result) # True
Merci beaucoup. Au fait, j'ai une question: est-ce que any (filter (regex.match, newlist)) a le même effet que votre code? Puisque je viens de lire dans le filtre python3, un itérateur n'est pas une liste complète.
@maplemaple Oui, mais essentiellement tout ce que vous faites avec cela est de vérifier si la longueur du filter (regex.match, newlist) est supérieure à 0. Je pense que ma version est un peu plus explicite.
@maplemaple FYI, j'ai ajouté une version légèrement plus rapide avec map .
Il y a encore un problème. Si je donne regex = re.compile ('the.') , le résultat doit être False puisque 'th.' ne figure pas dans la liste. Mais le code est toujours True
@maplemaple Ajoutez $ à votre regex pour en faire 'the. $' . $ signifie la fin de la chaîne.
Cela évaluera la liste jusqu'à ce qu'elle trouve la première correspondance.
t = time.process_time()
newlist = ['this','thiis','thas','sada']
search_for_match(newlist, r"th.s")
elapsed_time1 = time.process_time() - t
print(elapsed_time1) # 0.00015399999999998748
t2 = time.process_time()
newlist = ['this','thiis','thas','sada']
regex = re.compile('th.s')
result = any(regex.match(word) for word in newlist)
elapsed_time2 = time.process_time() - t2
print(elapsed_time2) # 1.1999999999900979e-05
t3 = time.process_time()
newlist = ['this','thiis','thas','sada']
regex = re.compile('th.s')
result = any(map(regex.match, newlist))
elapsed_time3 = time.process_time() - t3
print(elapsed_time3) # 5.999999999950489e-06
Ou pour la rendre plus générale:
def search_for_match(list, pattern):
result = False
for i in list:
if bool(re.match(pattern, i)) is True:
result = True
break
return result
newlist = ['this','thiis','thas','sada']
found = search_for_match(newlist, r"th.s")
print(found) # True
Juste pour coups de pied je les ai passés à travers le chronomètre. J'ai tellement perdu:
def search_for_match(list):
result = False
for i in newlist:
if bool(re.match(r"th.s", i)) is True:
result = True
break
return result
@ Tomothy32, je leur ai fait passer une minuterie parce que j'étais curieuse, pas parce que je ne vous croyais pas. Wow est le mien lent.
@CarlBrubaker Pas de problème. En passant, vous faussez les résultats en chronométrant tout, pas seulement cette ligne de code. Vous ne devez chronométrer que search_for_match (nouvelle liste, r "th.s") , result = any (regex.match (mot) pour mot dans la nouvelle liste) et result = any (map (regex.match, newlist)) individuellement. Le module timeit est également une meilleure idée, car il répète les tests plusieurs fois et est plus précis en général. En outre, en remarque, vous pouvez accélérer votre fonction en précompilant le regex.
Il y a encore un problème. Si je donne regex = re.compile ('the.') , le résultat doit être False puisque 'th.' ne figure pas dans la liste. Mais le code est toujours True
Je peux penser à (en plus d'utiliser n'importe quel)
next((x for x in newlist if regex.match(x)), False)
Ne renvoie pas True mais probablement OK pour les tests conditionnels si vous n'avez pas de chaînes vides :)
Utiliser
regexen premier lieu n'est peut-être pas la méthode la plus efficace ...Utilisez
any ()plutôt quefilter ()?Créez une seule chaîne à partir de newlist :
, this, thiis, thas, sada,. Gardez-le, puis exécutez un findall () , ou une seule correspondance en utilisant une nouvelle expression régulière construite, (th.s),. Cela vous donnera le['this', 'thas']ou TRUE / FALSE sans avoir à itérer.@Loocid Voulez-vous dire un (filtre (regex.match, nouvelle liste))? Il regarde toujours à travers tous les éléments de newlist pour retourner "True or False", non?
@Loocid Voulez-vous dire en python3 le filter () me donne un itérateur pas une liste complète, donc quand je compose any (), si ce n'est pas le pire des cas, il ne passera pas par tous les éléments de newlist pour retourner True?