Skip to content

Instantly share code, notes, and snippets.

@aruseni
Last active August 18, 2020 12:23
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save aruseni/1683896 to your computer and use it in GitHub Desktop.
Save aruseni/1683896 to your computer and use it in GitHub Desktop.
# -*- coding: utf-8 -*-
def transliterate(string):
capital_letters = {u'А': u'A',
u'Б': u'B',
u'В': u'V',
u'Г': u'G',
u'Д': u'D',
u'Е': u'E',
u'Ё': u'E',
u'Ж': u'Zh',
u'З': u'Z',
u'И': u'I',
u'Й': u'Y',
u'К': u'K',
u'Л': u'L',
u'М': u'M',
u'Н': u'N',
u'О': u'O',
u'П': u'P',
u'Р': u'R',
u'С': u'S',
u'Т': u'T',
u'У': u'U',
u'Ф': u'F',
u'Х': u'H',
u'Ц': u'Ts',
u'Ч': u'Ch',
u'Ш': u'Sh',
u'Щ': u'Sch',
u'Ъ': u'',
u'Ы': u'Y',
u'Ь': u'',
u'Э': u'E',
u'Ю': u'Yu',
u'Я': u'Ya',}
lower_case_letters = {u'а': u'a',
u'б': u'b',
u'в': u'v',
u'г': u'g',
u'д': u'd',
u'е': u'e',
u'ё': u'e',
u'ж': u'zh',
u'з': u'z',
u'и': u'i',
u'й': u'y',
u'к': u'k',
u'л': u'l',
u'м': u'm',
u'н': u'n',
u'о': u'o',
u'п': u'p',
u'р': u'r',
u'с': u's',
u'т': u't',
u'у': u'u',
u'ф': u'f',
u'х': u'h',
u'ц': u'ts',
u'ч': u'ch',
u'ш': u'sh',
u'щ': u'sch',
u'ъ': u'',
u'ы': u'y',
u'ь': u'',
u'э': u'e',
u'ю': u'yu',
u'я': u'ya',}
translit_string = ""
for index, char in enumerate(string):
if char in lower_case_letters.keys():
char = lower_case_letters[char]
elif char in capital_letters.keys():
char = capital_letters[char]
if len(string) > index+1:
if string[index+1] not in lower_case_letters.keys():
char = char.upper()
else:
char = char.upper()
translit_string += char
return translit_string
@bekbulatov
Copy link

If you want to check an existence key in dict, it's no need to call .key() method:

if char in lower_case_letters:
    char = lower_case_letters[char]

It works a little faster.

@aruseni
Copy link
Author

aruseni commented Jan 29, 2012

@bekbulatov
Thanks! :)

@tonal
Copy link

tonal commented Aug 6, 2013

Искал функцию транслитерации - наткнулся на хабровский пост.
Предлагаю несколько оптимизированный вариант:

_capital_letters = {
  u'А': u'A',
  u'Б': u'B',
  u'В': u'V',
  u'Г': u'G',
  u'Д': u'D',
  u'Е': u'E',
  u'Ё': u'E',
  u'Ж': u'Zh',
  u'З': u'Z',
  u'И': u'I',
  u'Й': u'Y',
  u'К': u'K',
  u'Л': u'L',
  u'М': u'M',
  u'Н': u'N',
  u'О': u'O',
  u'П': u'P',
  u'Р': u'R',
  u'С': u'S',
  u'Т': u'T',
  u'У': u'U',
  u'Ф': u'F',
  u'Х': u'H',
  u'Ц': u'Ts',
  u'Ч': u'Ch',
  u'Ш': u'Sh',
  u'Щ': u'Sch',
  u'Ъ': u'',
  u'Ы': u'Y',
  u'Ь': u'',
  u'Э': u'E',
  u'Ю': u'Yu',
  u'Я': u'Ya',}

_lower_case_letters = {
  u'а': u'a',
  u'б': u'b',
  u'в': u'v',
  u'г': u'g',
  u'д': u'd',
  u'е': u'e',
  u'ё': u'e',
  u'ж': u'zh',
  u'з': u'z',
  u'и': u'i',
  u'й': u'y',
  u'к': u'k',
  u'л': u'l',
  u'м': u'm',
  u'н': u'n',
  u'о': u'o',
  u'п': u'p',
  u'р': u'r',
  u'с': u's',
  u'т': u't',
  u'у': u'u',
  u'ф': u'f',
  u'х': u'h',
  u'ц': u'ts',
  u'ч': u'ch',
  u'ш': u'sh',
  u'щ': u'sch',
  u'ъ': u'',
  u'ы': u'y',
  u'ь': u'',
  u'э': u'e',
  u'ю': u'yu',
  u'я': u'ya',}

def transliterate(string):

  capital_letters = _capital_letters
  lower_case_letters = _lower_case_letters

  len_str = len(string)

  translit_string = u""

  for index, char in enumerate(string, 1):
    repl = lower_case_letters.get(char)
    if repl:
      translit_string += repl
      continue
    repl = capital_letters.get(char)
    if repl:
      if len_str > index:
        if string[index] not in lower_case_letters:
          repl = repl.upper()
      else:
        repl = repl.upper()
    else:
      repl = char
    translit_string += repl

  return translit_string

Изменения:

  1. Вынес массивы подстановок из функции - дабы не создавались на каждый вызов по новому
  2. Взятие длину строки вынес за цикл в локальную переменную.
  3. Поиск в списке ключей .keys() и последующую выборку по "[]" (О(н) + О(1)) заменил на .get() (О(1))
  4. Указал начинать индексировать с 1: enumerate(string, 1) дабы извавится от двойного index+1
    Думается, что на больших строках основные тормоза получались от п. 3 :)

@kalnauz-oleksandr
Copy link

return translit_string.replace('ь', '').replace('ъ', '').replace('Ь', '').replace('Ъ', '')

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment