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 символов.
Ответы
Ответ 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
, а затем перевести его в один вызов функции.