Перевод букв не в 7-битном ASCII в ASCII (например, с ñ на n и ą на a) - PullRequest
8 голосов
/ 20 января 2012

Я ищу быстрый и, возможно, удобный способ в Python 3 переводить строки с буквами не-ascii в слова только с буквами ascii.

Примеры!

żółw => zolw

móżdżek => mozdzek

łódź => Лодзь

и так далее ...

В национальных алфавитах много букв, которые можно превратить в буквы ASCII (например, от ñ до n). Я могу сделать это вручную для своего языка (польского), указав, как переводить каждую букву. Но есть ли какой-нибудь автоматизированный способ сделать это? Или какая-нибудь библиотека, которая будет делать то, что мне нужно?

Питоны str.encode() не пойдут, потому что "żółw".encode('ascii', 'replace') == "???w" и "żółw".encode('ascii', 'ignore') == "w" ...

Я могу сделать такой перевод для польских букв, но я не хочу делать это для любого другого языка:

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

Приведенный выше код делает то, что я хочу, с польскими буквами, но это уродливо: <Как лучше это сделать? </p>

Конечно, такие переводы изменят значения некоторых слов, но это нормально.

1 Ответ

6 голосов
/ 20 января 2012

Для этого может использоваться модуль unicodedata .У него есть функции для управления именами символов Unicode: name и lookup.

Теперь давайте посмотрим на них поближе.

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'

Видите образец?Давайте создадим функцию, которая его использует:

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'

Он ищет слово WITH в имени персонажа, удаляет все, что идет после него, и возвращает его обратно в lookup function.
Если нет ' WITH ', ValueError повышается, и когда нет символа с таким именем, KeyError повышается, поэтому функция возвращаетсимвол без изменений.

А вот функция, которая «переводит» строку на основе предыдущей функции:

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

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

Так что это решение, очевидно, очень хорошо, но я оставлю предыдущеениже.


Модуль unicodedata также имеет функцию, которая обещает аналогичные результаты - normalize с параметром 'NFKD' (декомпозиция совместимости), но он пропускает большинство символов.


Если у вас есть данные символов, предоставленный вами код можно улучшить.

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

Здесь хорошая таблица с символьными данными.Это JavaScript, но его можно легко использовать для Python.


И если вы не возражаете против использования внешних библиотек, вы можете попробовать Unidecode .Это было сделано только для этого.

...