Estoy escribiendo un programa de recuento de palabras en Python MapReduce. El problema es que hay muchos caracteres no alfabéticos esparcidos en los datos, he encontrado esta publicación Eliminando todo menos caracteres alfanuméricos de una cadena en Python que muestra una buena solución usando expresiones regulares, pero no estoy seguro de cómo implementarlo
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
Me temo que no estoy seguro de cómo usar la biblioteca re
o incluso la expresión regular para el caso. No estoy seguro de cómo aplicar el patrón de expresiones regulares a la cadena entrante (línea de un libro) v
correctamente para recuperar la nueva línea sin caracteres no alfanuméricos.
Sugerencias
v
es una línea completa de un libro (específicamente Moby Dick), voy palabra por palabra, no char por char. Así que algunas palabras pueden tener un "," al final, así que "indignidad" no se corresponde con "indignidad".Respuestas:
Utilizar
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'
Alternativamente, si solo desea eliminar un determinado conjunto de caracteres (ya que un apóstrofo podría estar bien en su entrada ...)
regex = re.compile('[,\.!?]') #etc.
fuente
^a-zA-Z
en lugar de sólo^a-zA-Z
a-zA-Z \n
. Estoy tratando de encontrar una expresión regular que agrupe a ambos en uno, pero usando\w
o\W
no me da el comportamiento deseado. Es posible que solo necesite agregar\n
si ese es el caso.Si prefiere no usar expresiones regulares, puede intentar
''.join([i for i in s if i.isalpha()])
fuente
Puede utilizar la función re.sub () para eliminar estos caracteres:
>>> import re >>> re.sub("[^a-zA-Z]+", "", "ABC12abc345def") 'ABCabcdef'
re.sub (COINCIDIR PATRÓN, REEMPLAZAR CADENA, CADENA PARA BUSCAR)
"[^a-zA-Z]+"
- busque cualquier grupo de caracteres que NO sean a-zA-z.""
- Reemplazar los caracteres coincidentes con ""fuente
Tratar:
s = ''.join(filter(str.isalnum, s))
Esto tomará todos los caracteres de la cadena, mantendrá solo los alfanuméricos y construirá una cadena a partir de ellos.
fuente
El método más rápido es 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
fuente
Es recomendable utilizar el módulo PyPi
regex
si planea hacer coincidir clases de propiedad Unicode específicas. Esta biblioteca también ha demostrado ser más estable, especialmente en el manejo de textos grandes, y produce resultados consistentes en varias versiones de Python. Todo lo que necesita hacer es mantenerlo actualizado.Si lo instala (usando
pip intall regex
opip3 install regex
), puede usarimport regex print ( regex.sub(r'\P{L}+', '', 'ABCŁąć1-2!Абв3§4“5def”') ) // => ABCŁąćАбвdef
para eliminar todos los fragmentos de 1 o más caracteres que no sean letras Unicode de
text
. Vea una demostración de Python en línea . También puede utilizar"".join(regex.findall(r'\p{L}+', 'ABCŁąć1-2!Абв3§4“5def”'))
para obtener el mismo resultado.En Python
re
, para hacer coincidir cualquier letra Unicode, se puede usar la[^\W\d_]
construcción (¿ Coincidir con cualquier letra Unicode? ).Por lo tanto, para eliminar todos los caracteres que no sean letras, puede hacer coincidir todas las letras y unir los resultados:
result = "".join(re.findall(r'[^\W\d_]', text))
O elimine todos los caracteres que no coincidan con
[^\W\d_]
:result = re.sub(r'([^\W\d_])|.', r'\1', text, re.DOTALL)
Vea la demostración de expresiones regulares en línea . Sin embargo , es posible que obtenga resultados inconsistentes en varias versiones de Python porque el estándar Unicode está evolucionando y el conjunto de caracteres que coincidan
\w
dependerá de la versión de Python.regex
Se recomienda encarecidamente utilizar la biblioteca PyPi para obtener resultados consistentes.fuente