Подтвердить что ты не робот

Python: эффективный метод замены акцентов (от e до e), удалить [^ a-zA-Z\d\s] и lower()

Использование Python 3.3. Я хочу сделать следующее:

  • заменить специальные алфавитные символы, такие как e sharp (é) и o circumflex (ô) с базовым символом (например, от o до o)
  • удалить все символы, кроме буквенно-цифровых и пробелы между буквенно-цифровыми символы
  • конвертировать в нижний регистр

Это то, что у меня есть до сих пор:

mystring_modified = mystring.replace('\u00E9', 'e').replace('\u00F4', 'o').lower()
alphnumspace = re.compile(r"[^a-zA-Z\d\s]")
mystring_modified = alphnumspace.sub('', mystring_modified)

Как я могу улучшить это? Эффективность вызывает большую озабоченность, тем более что я выполняю операции внутри цикла:

# Pseudocode
for mystring in myfile:
    mystring_modified = # operations described above
    mylist.append(mystring_modified)

Файлы, о которых идет речь, составляют около 200 000 символов.

4b9b3361

Ответ 1

>>> import unicodedata
>>> s='éô'
>>> ''.join((c for c in unicodedata.normalize('NFD', s) if unicodedata.category(c) != 'Mn'))
'eo'

Также проверьте unidecode

Что предлагает Unidecode - это средняя дорога: функция unidecode() принимает Unicode и пытается представить его в символах ASCII (т.е. универсально отображаемые символы между 0x00 и 0x7F), где компромиссы, принятые при отображении между двумя наборами символов чтобы быть рядом с человеком, который выбрал бы клавиатуру США.

Качество результирующего представления ASCII меняется. Для языков западное происхождение это должно быть между совершенным и хорошим. С другой (т.е. передача римскими буквами произношение, выраженное текстом в какой-либо другой системе письма) такие языки, как китайский, японский или корейский, являются очень сложной проблемой и эта библиотека даже не пытается ее решить. Он рисует линию на контекстно-зависимое сопоставление символов. Итак, хорошее эмпирическое правило заключается в том, что чем дальше script вы транслитерируете, так это латинский алфавит, тем хуже будет транслитерация.

Обратите внимание, что этот модуль обычно дает лучшие результаты, чем просто снятие акцентов с символов (что можно сделать на Python с встроенные функции). Он основан на настраиваемых символами персонажах, которые например, также содержат приближения ASCII для символов и нелатинские алфавиты.

Ответ 2

Вы можете использовать str.translate:

import collections
import string

table = collections.defaultdict(lambda: None)
table.update({
    ord('é'):'e',
    ord('ô'):'o',
    ord(' '):' ',
    ord('\N{NO-BREAK SPACE}'): ' ',
    ord('\N{EN SPACE}'): ' ',
    ord('\N{EM SPACE}'): ' ',
    ord('\N{THREE-PER-EM SPACE}'): ' ',
    ord('\N{FOUR-PER-EM SPACE}'): ' ',
    ord('\N{SIX-PER-EM SPACE}'): ' ',
    ord('\N{FIGURE SPACE}'): ' ',
    ord('\N{PUNCTUATION SPACE}'): ' ',
    ord('\N{THIN SPACE}'): ' ',
    ord('\N{HAIR SPACE}'): ' ',
    ord('\N{ZERO WIDTH SPACE}'): ' ',
    ord('\N{NARROW NO-BREAK SPACE}'): ' ',
    ord('\N{MEDIUM MATHEMATICAL SPACE}'): ' ',
    ord('\N{IDEOGRAPHIC SPACE}'): ' ',
    ord('\N{IDEOGRAPHIC HALF FILL SPACE}'): ' ',
    ord('\N{ZERO WIDTH NO-BREAK SPACE}'): ' ',
    ord('\N{TAG SPACE}'): ' ',
    })
table.update(dict(zip(map(ord,string.ascii_uppercase), string.ascii_lowercase)))
table.update(dict(zip(map(ord,string.ascii_lowercase), string.ascii_lowercase)))
table.update(dict(zip(map(ord,string.digits), string.digits)))

print('123 fôé BAR҉'.translate(table,))

дает

123 foe bar

Внизу вы должны будете перечислить все специальные символы с акцентом, которые вы хотите перевести. Метод @gnibbler требует меньше кодирования.

В верхней части метод str.translate должен быть довольно быстрым, и он может обрабатывать все ваши требования (удаление, удаление и удаление акцентов) в одном вызове функции после настройки table.


Кстати, файл с 200K-символами не очень большой. Таким образом, было бы более полезно прочитать весь файл в один str, а затем перевести его в один вызов функции.