2012-01-19 7 views
8

Sto cercando un modo veloce e possibilmente conveniente in Python 3 per tradurre stringhe con lettere non ascii in parole con solo lettere ascii.Conversione di lettere non in ASCII a 7 bit in ASCII (come da ń a n e ą a a)

Esempi!

żółw => żółw

móżdżek => mozdzek

Łódź => Lodz

e così via ...

Ci sono molte lettere in alfabeti nazionali che possono essere trasformati in Lettere ASCII (come da ñ a n). Posso farlo manualmente per la mia lingua (polacco), specificando come tradurre ogni lettera. Ma esiste un modo automatico per farlo? O qualche biblioteca che farebbe quello che mi serve?

Pythons str.encode() non lo farà, perché "żółw".encode('ascii', 'replace') == "???w" e "żółw".encode('ascii', 'ignore') == "w" ...

posso fare tale traduzione per le lettere polacchi, ma non voglio farlo per tutte le altre lingue:

>>> 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' 

Il codice sopra fa quello che voglio con le lettere polacche, ma è brutto: < Qual è il modo migliore per farlo?

Naturalmente tali traduzioni cambieranno il significato di alcune parole, ma questo è ok.

+1

Ricordare che in alcune lingue ciò che alcuni considererebbero una lettera accentata è considerato una lettera distinta in quella lingua. Ad esempio, la lettera "å" in svedese è tipicamente considerata una lettera distinta da "a", e non semplicemente la lettera "a" con un anello sopra di essa. – dreamlax

+0

Ne sono consapevole ... Il punto è che quando scrivo in polacco da qualche parte, dove le mie lettere nazionali non sono supportate, uso queste "traduzioni" di cui ho scritto. Immagino che persone di altri paesi abbiano i propri modi di scrivere in tali ambienti. Mi piacerebbe sapere come si possono fare tali trasformazioni. – Maciek

+0

@John Saunders, grazie per aver reso la mia risposta completamente invalida. –

risposta

5

Per questo è possibile utilizzare il modulo unicodedata. Dispone di funzioni per manipolare i nomi dei caratteri Unicode: name e lookup.

Ora guardiamoli più da vicino.

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' 

Vedere uno schema? Facciamo una funzione che lo utilizza:

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' 

Sembra la parola CON nel nome del personaggio, rimuove tutto ciò che va dopo che e la immette di nuovo alla funzione lookup.
Se non c'è 'CON', ValueError si solleva e, quando non v'è alcun personaggio con questo nome, KeyError è sollevato, in modo che la funzione restituisce il carattere invariato.

E qui è una funzione che "traduce" una stringa in base alla funzione precedente:

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

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

Quindi questa soluzione è ovviamente molto buono, ma lascio i precedenti di seguito.


Il modulo unicodedata ha anche una funzione che promette risultati simili – normalize con 'NFKD' parametro (compatibilità decomposizione), ma non trova maggior parte dei caratteri.


Se si dispone dei dati di carattere, il codice fornito può essere migliorato.

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

Here è un bel tavolo con i dati di caratteri. Questo è JavaScript ma può essere facilmente utilizzato per Python.


E se non ti dispiace utilizzando librerie esterne, si potrebbe desiderare di provare Unidecode. E 'stato fatto solo per questo.

+0

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

+0

Che ne dici di decomporre a NFD e poi buttare via tutti i segni combinati? –

+0

Questo tavolo ti è piaciuto è grande e questo La libreria Unidecode è abbastanza promettente! Per ora penso che non ci siano modi migliori per farlo – Maciek

Problemi correlati