Estou escrevendo um programa de contagem de palavras MapReduce em python. O problema é que existem muitos caracteres não alfabéticos espalhados nos dados, encontrei este post Removendo tudo, exceto caracteres alfanuméricos de uma string em Python, que mostra uma boa solução usando regex, mas não tenho certeza de como implementá-lo
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
Infelizmente, não tenho certeza de como usar a biblioteca re
ou mesmo regex para esse assunto. Não tenho certeza de como aplicar o padrão regex à string de entrada (linha de um livro) v
para recuperar a nova linha sem caracteres não alfanuméricos.
Sugestões?
v
é uma linha inteira de um livro (especificamente moby dick), estou falando palavra por palavra, não char por char. Portanto, algumas palavras podem ter um "," no final, então "indignidade", não mapeia com "indignidade".Respostas:
Usar
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, se você deseja remover apenas um determinado conjunto de caracteres (como um apóstrofo pode ser adequado em sua entrada ...)
regex = re.compile('[,\.!?]') #etc.
fonte
^a-zA-Z
vez de apenas^a-zA-Z
a-zA-Z \n
. Estou tentando encontrar uma regex que agrupe ambos em um, mas usando\w
ou\W
não me dando o comportamento desejado. Você só precisa adicionar\n
se for esse o caso.Se você preferir não usar regex, você pode tentar
''.join([i for i in s if i.isalpha()])
fonte
Você pode usar a função re.sub () para remover estes caracteres:
>>> import re >>> re.sub("[^a-zA-Z]+", "", "ABC12abc345def") 'ABCabcdef'
re.sub (CORRESPONDER PADRÃO, SUBSTITUIR CADEIA, CADEIA PARA PESQUISAR)
"[^a-zA-Z]+"
- procure qualquer grupo de caracteres que NÃO seja a-zA-z.""
- Substitua os caracteres correspondentes por ""fonte
Experimentar:
s = ''.join(filter(str.isalnum, s))
Isso pegará todos os caracteres da string, manterá apenas os alfanuméricos e construirá uma string a partir deles.
fonte
O método mais rápido é 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
fonte
É aconselhável usar o módulo PyPi
regex
se você planeja combinar classes de propriedade Unicode específicas. Esta biblioteca também provou ser mais estável, especialmente lidando com textos grandes e produz resultados consistentes em várias versões do Python. Tudo o que você precisa fazer é mantê-lo atualizado.Se você instalá-lo (usando
pip intall regex
oupip3 install regex
), você pode usarimport regex print ( regex.sub(r'\P{L}+', '', 'ABCŁąć1-2!Абв3§4“5def”') ) // => ABCŁąćАбвdef
para remover todos os blocos de 1 ou mais caracteres diferentes de letras Unicode de
text
. Veja uma demonstração online do Python . Você também pode usar"".join(regex.findall(r'\p{L}+', 'ABCŁąć1-2!Абв3§4“5def”'))
para obter o mesmo resultado.Em Python
re
, para corresponder a qualquer letra Unicode, pode-se usar a[^\W\d_]
construção ( Corresponder a qualquer letra Unicode? ).Portanto, para remover todos os caracteres que não são letras, você pode combinar todas as letras e juntar os resultados:
result = "".join(re.findall(r'[^\W\d_]', text))
Ou remova todos os caracteres diferentes daqueles correspondidos com
[^\W\d_]
:result = re.sub(r'([^\W\d_])|.', r'\1', text, re.DOTALL)
Veja a demonstração de regex online . No entanto , você pode obter resultados inconsistentes em várias versões do Python porque o padrão Unicode está evoluindo e o conjunto de caracteres correspondentes
\w
dependerá da versão do Python. Usar aregex
biblioteca PyPi é altamente recomendável para obter resultados consistentes.fonte