J'écris un programme de comptage de mots MapReduce en python. Le problème est qu'il y a beaucoup de caractères non alphabétiques éparpillés dans les données, j'ai trouvé ce post Supprimant tout sauf les caractères alphanumériques d'une chaîne en Python qui montre une belle solution utilisant regex, mais je ne sais pas comment l'implémenter
def mapfn(k, v):
print v
import re, string
pattern = re.compile('[\W_]+')
v = pattern.match(v)
print v
for w in v.split():
yield w, 1
J'ai peur de ne pas savoir comment utiliser la bibliothèque re
ou même l'expression régulière pour cette question. Je ne sais pas comment appliquer v
correctement le motif regex à la chaîne entrante (ligne d'un livre) pour récupérer la nouvelle ligne sans aucun caractère non alphanumérique.
Suggestions?
v
est une ligne entière d'un livre (en particulier moby dick), je vais mot par mot et non caractère par caractère. Ainsi, certains mots peuvent avoir un "," à la fin, donc "indignité" ne correspond pas à "indignité".Réponses:
Utilisation
re.sub
import re regex = re.compile('[^a-zA-Z]') #First parameter is the replacement, second parameter is your input string regex.sub('', 'ab3d*E') #Out: 'abdE'
Alternativement, si vous ne voulez supprimer qu'un certain jeu de caractères (comme une apostrophe peut convenir dans votre entrée ...)
regex = re.compile('[,\.!?]') #etc.
la source
^a-zA-Z
au lieu de juste^a-zA-Z
a-zA-Z \n
. J'essaie de trouver une expression régulière qui regrouperait les deux en un mais qui ne me donne pas\w
ou\W
ne me donne pas le comportement souhaité. Vous devrez peut-être simplement ajouter\n
si c'est le cas.Si vous préférez ne pas utiliser regex, vous pouvez essayer
''.join([i for i in s if i.isalpha()])
la source
Vous pouvez utiliser la fonction re.sub () pour supprimer ces caractères:
>>> import re >>> re.sub("[^a-zA-Z]+", "", "ABC12abc345def") 'ABCabcdef'
re.sub (MATCH PATTERN, REMPLACE STRING, STRING TO SEARCH)
"[^a-zA-Z]+"
- recherchez tout groupe de caractères qui ne sont PAS a-zA-z.""
- Remplacez les caractères correspondants par ""la source
Essayer:
s = ''.join(filter(str.isalnum, s))
Cela prendra tous les caractères de la chaîne, ne conservera que les caractères alphanumériques et construira une chaîne à partir d'eux.
la source
La méthode la plus rapide est regex
#Try with regex first t0 = timeit.timeit(""" s = r2.sub('', st) """, setup = """ import re r2 = re.compile(r'[^a-zA-Z0-9]', re.MULTILINE) st = 'abcdefghijklmnopqrstuvwxyz123456789!@#$%^&*()-=_+' """, number = 1000000) print(t0) #Try with join method on filter t0 = timeit.timeit(""" s = ''.join(filter(str.isalnum, st)) """, setup = """ st = 'abcdefghijklmnopqrstuvwxyz123456789!@#$%^&*()-=_+' """, number = 1000000) print(t0) #Try with only join t0 = timeit.timeit(""" s = ''.join(c for c in st if c.isalnum()) """, setup = """ st = 'abcdefghijklmnopqrstuvwxyz123456789!@#$%^&*()-=_+' """, number = 1000000) print(t0) 2.6002226710006653 Method 1 Regex 5.739747313000407 Method 2 Filter + Join 6.540099570000166 Method 3 Join
la source
Il est conseillé d'utiliser le module PyPi
regex
si vous prévoyez de faire correspondre des classes de propriétés Unicode spécifiques. Cette bibliothèque s'est également avérée plus stable, en particulier pour la gestion de textes volumineux, et donne des résultats cohérents dans différentes versions de Python. Tout ce que vous avez à faire est de le maintenir à jour.Si vous l'installez (en utilisant
pip intall regex
oupip3 install regex
), vous pouvez utiliserimport regex print ( regex.sub(r'\P{L}+', '', 'ABCŁąć1-2!Абв3§4“5def”') ) // => ABCŁąćАбвdef
pour supprimer tous les blocs de 1 ou plusieurs caractères autres que les lettres Unicode de
text
. Voir une démo Python en ligne . Vous pouvez également utiliser"".join(regex.findall(r'\p{L}+', 'ABCŁąć1-2!Абв3§4“5def”'))
pour obtenir le même résultat.En Python
re
, pour faire correspondre n'importe quelle lettre Unicode, on peut utiliser la[^\W\d_]
construction ( Match any Unicode letter? ).Ainsi, pour supprimer tous les caractères autres que des lettres, vous pouvez soit faire correspondre toutes les lettres et joindre les résultats:
result = "".join(re.findall(r'[^\W\d_]', text))
Ou supprimez tous les caractères autres que ceux correspondant à
[^\W\d_]
:result = re.sub(r'([^\W\d_])|.', r'\1', text, re.DOTALL)
Voir la démo regex en ligne . Cependant , vous pouvez obtenir des résultats incohérents entre les différentes versions de Python car le standard Unicode évolue et le jeu de caractères correspondant
\w
dépendra de la version de Python. L'utilisation de laregex
bibliothèque PyPi est fortement recommandée pour obtenir des résultats cohérents.la source