2012-01-19 13 views
8

Estoy buscando una manera rápida y posiblemente conveniente en Python 3 para traducir cadenas con letras que no sean ascii a palabras con solo letras ascii.Traducir letras no en 7 bits ASCII a ASCII (como ñ a n y ± aa)

¡Ejemplos!

Żółw => Żółw

móżdżek => mozdzek

łódź => Lodz

y así sucesivamente ...

Hay muchas cartas en alfabetos nacionales que se pueden convertir en Letras ASCII (como ń a n). Puedo hacerlo manualmente para mi idioma (polaco), especificando cómo traducir cada letra. ¿Pero hay alguna forma automatizada para hacer eso? ¿O alguna biblioteca que haría lo que necesito?

pitones str.encode() no va a hacer, porque "żółw".encode('ascii', 'replace') == "???w" y "żółw".encode('ascii', 'ignore') == "w" ...

que pueda hacer dicha traducción para las letras polacas, pero no quiero que lo haga por cualquier otro idioma:

>>> utf8_letters = ['ą','ę','ć','ź','ż','ó','ł','ń','ś'] 
>>> ascii_letters = ['a','e','c','z','z','o','l','n','s'] 
>>> trans_dict = dict(zip(utf8_letters,ascii_letters)) 
>>> turtle = "żółw" 
>>> out = [] 
>>> for l in turtle: 
... out.append(trans_dict[l] if l in trans_dict else l) 
>>> result = ''.join(out) 
>>> result 
'zolw' 

El código anterior hace lo que yo quiero con letras polacas, pero es feo: < ¿Cuál es la mejor manera de hacerlo?

Por supuesto, tales traducciones cambiarán el significado de algunas palabras, pero eso está bien.

+1

Tenga en cuenta que en algunos idiomas, lo que algunos considerarían una letra acentuada se considera una letra distinta en ese idioma. Por ejemplo, la letra 'å' en sueco generalmente se considera una letra distinta de 'a', y no simplemente la letra 'a' con un anillo encima de ella. – dreamlax

+0

Soy consciente de eso ... El punto es que cuando escribo en polaco en algún lugar, donde mis letras nacionales no son compatibles, uso estas "traducciones" sobre las que escribí. Creo que las personas de otros países tienen sus propias formas de escribir en esos entornos. Me gustaría saber cómo se pueden hacer tales transformaciones. – Maciek

+0

@ John Saunders, gracias por hacer que mi respuesta sea completamente inválida. –

Respuesta

5

El módulo unicodedata se puede usar para esto. Tiene funciones para manipular nombres de caracteres Unicode: name y lookup.

Ahora veámoslos más de cerca.

name('Ż') == 'LATIN CAPITAL LETTER Z WITH DOT ABOVE' 
name('ł') == 'LATIN SMALL LETTER L WITH STROKE' 
lookup('LATIN CAPITAL LETTER Z') == 'Z' 
lookup('LATIN SMALL LETTER L') == 'l' 

¿Ves un patrón? Vamos a hacer una función que lo utiliza:

import unicodedata 

def normalize_char(c): 
    try: 
     cname = unicodedata.name(c) 
     cname = cname[:cname.index(' WITH')] 
     return unicodedata.lookup(cname) 
    except (ValueError, KeyError): 
     return c 

normalize_char('ę') == 'e' 
normalize_char('Ę') == 'E' 
normalize_char('ś') == 's' 

Busca la palabra CON en el nombre del personaje, elimina todo lo que va tras ella y se alimenta de nuevo a la función lookup.
Si no aparece 'WITH', se genera ValueError y cuando no hay un carácter con dicho nombre, KeyError se activa, por lo que la función no cambia el carácter.

Y aquí es una función que "traduce" una cadena basada en la función anterior:

def normalize(s): 
    return ''.join(normalize_char(c) for c in s) 

normalize('Móżdżek') == 'Mozdzek' 

lo que esta solución es, obviamente, muy bueno, pero voy a dejar las anteriores continuación.


El módulo unicodedata también tiene una función que promete resultados similares – normalize con 'NFKD' parámetro (descomposición de compatibilidad), pero no alcanza la mayoría de los personajes.


Si tiene los datos de los caracteres, el código proporcionado puede mejorarse.

letters={'ł':'l', 'ą':'a', 'ń':'n', 'ć':'c', 'ó':'o', 'ę':'e', 'ś':'s', 'ź':'z', 'ż':'z'} 
trans=str.maketrans(letters) 
result=text.translate(trans) 

Here es una mesa con datos de caracteres. Esto es JavaScript pero se puede usar fácilmente para Python.


Y si no les importa usar bibliotecas externas, es posible que desee probar Unidecode. Fue hecho solo para esto.

+0

Unfortunatley unicodedata.normalize ('NFKD', "żółw") == 'żółw' no 'zolw' :( – Maciek

+0

¿Qué hay de descomponer a NFD y luego tirar todas las marcas de combinación? –

+0

Esta tabla te ha gustado es genial y esto La biblioteca de Unidecode es bastante prometedora. Por ahora, creo que no hay mejores formas de hacerlo. – Maciek

Cuestiones relacionadas