почему для длинных строк IndexError
есть функция для транслитерации польских слов
def transcript(s: str) -> str:
result = ''
table = {'a': 'а', 'la': 'я', 'ą': 'он', 'ąb': 'ом', 'ąp': 'ом', 'lą': 'ьон', 'ląp': 'ьом', 'ląb': 'ьом', 'b': 'б',
'c': 'ц', 'сh': 'х', 'cz': 'ч', 'ć': 'ць', 'd': 'д', 'dz': 'дз', 'dź': 'дзь', 'dż': 'дж', 'e': 'е',
'ę': 'ен', 'ęb': 'ем', 'ęp': 'ем', 'f': 'ф', 'g': 'ґ', 'h': 'г', 'i': 'і', 'ia': 'я', 'bia': '’я',
'pia': '’я', 'wia': '’я', 'ią': 'ьон', 'bią': 'йон', 'pią': 'йон', 'wią': 'йон', 'iąp': 'йом',
'iąb': 'йом', 'ię': 'єн', 'bię': '’єн', 'pię': '’єн', 'mię': '’єн', 'ięb': 'єм', 'ięp': 'єм',
'bięb': '’єм', 'pięb': '’єм', 'mięb': '’єм', 'bięp': '’єм', 'pięp': '’єм', 'mięp': '’єм', 'io': 'ьо',
'ió': 'ю', 'pió': '’ю', 'bió': '’ю', 'wió': '’ю', 'iu': 'ю', 'j': 'й', 'ja': 'я', 'ją': 'йон',
'jąb': 'ьом', 'jąp': 'ьом', 'bją': 'йом', 'pją': 'йом', 'je': 'є', 'ję': '’єн', 'jęb': 'єм', 'jęp': 'єм',
'jo': 'йо', 'jó': 'ью', 'ju': 'ю', 'k': 'к', 'l': 'л', 'ł': 'л', 'm': 'м', 'n': 'н', 'ń': 'нь', 'o': 'о',
'lo': 'у', 'ló': 'ю', 'p': 'п', 'r': 'р', 'z': 'з', 'rz': 'ж', 'chrz': 'ш', 'krz': 'ш', 'prz': 'ш',
'trz': 'ш', 'rzch': 'ш', 'rzk': 'ш', 'rzp': 'ш', 'rzt': 'ш', 's': 'с', 'sz': 'ш', 'szcz': 'щ', 'ś': 'сь',
't': 'т', 'u': 'у', 'lu': 'ю', 'w': 'в', 'y': 'и', 'z': 'з', 'ź': 'зь', 'ż': 'ж', 'ó': 'у',
}
i = 0
while True:
if i > len(s):
break
if s[i:i + 4] in table:
if s[i:i + 4][0].isupper():
result += table[s[i:i + 4].lower()].capitalize()
else:
result += table[s[i:i + 4]]
i += 4
elif s[i:i + 3] in table:
if s[i:i + 3][0].isupper():
result += table[s[i:i + 3].lower()].capitalize()
else:
result += table[s[i:i + 3]]
i += 3
elif s[i:i + 2] in table:
if s[i:i + 2][0].isupper():
result += table[s[i:i + 2].lower()].capitalize()
else:
result += table[s[i:i + 2]]
i += 2
elif s[i] in table:
if s[i].isupper():
result += table[s[i].lower()].upper()
else:
result += table[s[i]]
i += 1
else:
if s[i].isalpha():
if s[i][0].isupper():
result += table[s[i].lower()].upper()
else:
result += s[i]
else:
result += s[i]
i += 1
return result
для кратких строк к примеру Od niedawna szósty stycznia jest работает отлично, но когда передать к примеру Od niedawna szósty stycznia jest znowu w Polsce wolnym dniem. To bardzo stare święto, związane z Bożym Narodzeniem. Obchodzi się je na pamiątkę mędrców ze Wschodu, którzy za Gwiazdą przyszli do Betlejem i złożyli dary Jezusowi. Popularnie nazywani są: Kacper, Melchior i Baltazar. Na drzwiach wejściowych pisze się kredą ich inicjały oraz aktualny rok. Wielkanoc to najważniejsze święto chrześcijańskie upamiętniające Zmartwychwstanie Jezusa Chrystusa. To święto ruchome, obchodzi się je w pierwszą niedzielę po pierwszej wiosennej pełni księżyca. Najwcześniej dwudziestego drugiego marca, a najpóźniej dwudziestego piątego kwietnia.
получаю ошибку
Traceback (most recent call last): File "/Users/andriykmit/PycharmProjects/pol-ua/main.py", line 59, in print(transcript('''Od niedawna szósty stycznia jest znowu w Polsce wolnym dniem. To bardzo stare święto, związane z Bożym Narodzeniem. Obchodzi się je na pamiątkę mędrców ze Wschodu, którzy za Gwiazdą przyszli do Betlejem i złożyli dary Jezusowi. Popularnie nazywani są: Kacper, Melchior i Baltazar. Na drzwiach wejściowych pisze się kredą ich inicjały oraz aktualny rok. File "/Users/andriykmit/PycharmProjects/pol-ua/main.py", line 40, in transcript elif s[i] in table: IndexError: string index out of range
Ответы (3 шт):
Ошибка возникает, если строка заканчивается не на букву (а на точку или пробел итд). От длины строки не зависит.
Заменить
while True:
if i > len(s):
break
на
while i < len(s):
Тогда не будет вылета за границу строки.
Вторая ошибка - нет приведения к нижнему регистру когда делается
if s[i:i + 4] in table. Соответственно, при первой заглавной букве до последующего условия if s[i:i + 4][0].isupper() дело не дойдёт.
Ну и вообще, все замены можно в один регексп уложить:
import re
def transcript(s: str) -> str:
table = {'a': 'а', 'la': 'я', 'ą': 'он', 'ąb': 'ом', 'ąp': 'ом', 'lą': 'ьон', 'ląp': 'ьом', 'ląb': 'ьом', 'b': 'б',
'c': 'ц', 'сh': 'х', 'cz': 'ч', 'ć': 'ць', 'd': 'д', 'dz': 'дз', 'dź': 'дзь', 'dż': 'дж', 'e': 'е',
'ę': 'ен', 'ęb': 'ем', 'ęp': 'ем', 'f': 'ф', 'g': 'ґ', 'h': 'г', 'i': 'і', 'ia': 'я', 'bia': '’я',
'pia': '’я', 'wia': '’я', 'ią': 'ьон', 'bią': 'йон', 'pią': 'йон', 'wią': 'йон', 'iąp': 'йом',
'iąb': 'йом', 'ię': 'єн', 'bię': '’єн', 'pię': '’єн', 'mię': '’єн', 'ięb': 'єм', 'ięp': 'єм',
'bięb': '’єм', 'pięb': '’єм', 'mięb': '’єм', 'bięp': '’єм', 'pięp': '’єм', 'mięp': '’єм', 'io': 'ьо',
'ió': 'ю', 'pió': '’ю', 'bió': '’ю', 'wió': '’ю', 'iu': 'ю', 'j': 'й', 'ja': 'я', 'ją': 'йон',
'jąb': 'ьом', 'jąp': 'ьом', 'bją': 'йом', 'pją': 'йом', 'je': 'є', 'ję': '’єн', 'jęb': 'єм', 'jęp': 'єм',
'jo': 'йо', 'jó': 'ью', 'ju': 'ю', 'k': 'к', 'l': 'л', 'ł': 'л', 'm': 'м', 'n': 'н', 'ń': 'нь', 'o': 'о',
'lo': 'у', 'ló': 'ю', 'p': 'п', 'r': 'р', 'z': 'з', 'rz': 'ж', 'chrz': 'ш', 'krz': 'ш', 'prz': 'ш',
'trz': 'ш', 'rzch': 'ш', 'rzk': 'ш', 'rzp': 'ш', 'rzt': 'ш', 's': 'с', 'sz': 'ш', 'szcz': 'щ', 'ś': 'сь',
't': 'т', 'u': 'у', 'lu': 'ю', 'w': 'в', 'y': 'и', 'z': 'з', 'ź': 'зь', 'ż': 'ж', 'ó': 'у',
}
return re.sub("|".join(map(re.escape, sorted(table, key=len, reverse=True))), lambda m: table[m.group(0).lower()].capitalize() if m.group(0)[0].isupper() else table[m.group(0).lower()], s, flags=re.I)
Немного сократил повторы кода и задействовал join для строк:
def transcript(s: str) -> str:
table = {'a': 'а', 'la': 'я', 'ą': 'он', 'ąb': 'ом', 'ąp': 'ом', 'lą': 'ьон', 'ląp': 'ьом', 'ląb': 'ьом', 'b': 'б',
'c': 'ц', 'сh': 'х', 'cz': 'ч', 'ć': 'ць', 'd': 'д', 'dz': 'дз', 'dź': 'дзь', 'dż': 'дж', 'e': 'е',
'ę': 'ен', 'ęb': 'ем', 'ęp': 'ем', 'f': 'ф', 'g': 'ґ', 'h': 'г', 'i': 'і', 'ia': 'я', 'bia': '’я',
'pia': '’я', 'wia': '’я', 'ią': 'ьон', 'bią': 'йон', 'pią': 'йон', 'wią': 'йон', 'iąp': 'йом',
'iąb': 'йом', 'ię': 'єн', 'bię': '’єн', 'pię': '’єн', 'mię': '’єн', 'ięb': 'єм', 'ięp': 'єм',
'bięb': '’єм', 'pięb': '’єм', 'mięb': '’єм', 'bięp': '’єм', 'pięp': '’єм', 'mięp': '’єм', 'io': 'ьо',
'ió': 'ю', 'pió': '’ю', 'bió': '’ю', 'wió': '’ю', 'iu': 'ю', 'j': 'й', 'ja': 'я', 'ją': 'йон',
'jąb': 'ьом', 'jąp': 'ьом', 'bją': 'йом', 'pją': 'йом', 'je': 'є', 'ję': '’єн', 'jęb': 'єм', 'jęp': 'єм',
'jo': 'йо', 'jó': 'ью', 'ju': 'ю', 'k': 'к', 'l': 'л', 'ł': 'л', 'm': 'м', 'n': 'н', 'ń': 'нь', 'o': 'о',
'lo': 'у', 'ló': 'ю', 'p': 'п', 'r': 'р', 'z': 'з', 'rz': 'ж', 'chrz': 'ш', 'krz': 'ш', 'prz': 'ш',
'trz': 'ш', 'rzch': 'ш', 'rzk': 'ш', 'rzp': 'ш', 'rzt': 'ш', 's': 'с', 'sz': 'ш', 'szcz': 'щ', 'ś': 'сь',
't': 'т', 'u': 'у', 'lu': 'ю', 'w': 'в', 'y': 'и', 'z': 'з', 'ź': 'зь', 'ż': 'ж', 'ó': 'у',
}
res = []
i = 0
while i < len(s):
for j in range(4, 0, -1):
m = s[i:i + j].lower()
if m in table:
if s[i].isupper():
res.append(table[m].capitalize())
else:
res.append(table[m])
i += j
break
else:
res.append(s[i])
i += 1
return "".join(res)
print(transcript("abcd bia. Cd Cz CZ cz cZ."))
# абцд ’я. Цд Ч Ч ч ч.