Вы печатаете Кодовые точки Unicode малаялам , в которых используется множество знаков гласных для изменения предыдущего глифа.Эти кодовые точки с гласными знаками, которые сами по себе не образуют новую букву, и малаялам не выдают в терминале ту же обычную ширину вывода, что и буквы ASCII.
Например, ваша первая строка начинается с U + 0D38 МАЛАЯЛАМ ПИСЬМО SA и U + 0D3F МАЛАЯЛАМ ГЛАГОЛЬНЫЙ ЗНАК I .Первый, буква SA , занимает полную позицию на экране, а второй символ, знак гласного I , перед SA, изменяет способ печати буквы.Обратите внимание, что при печати 2 кодовых точек имеется только один видимый глиф:
>>> print u'\u0d38' # letter SA
സ
>>> print u'\u0d3f' # vowel sign I
ി
>>> print u'\u0d38\u0d3f' # both together
സി
Ширина кодовых точек малаялам также различна;если вы добавляете буквы ASCII ниже SA и гласный знак I, отдельно и вместе, это выглядит следующим образом:
>>> print u'\u0d38\nA..\n\u0d3f\nB..\n\u0d38\u0d3f\nAB.' # with ASCII letters for size
സ
A..
ി
B..
സി
AB.
Обратите внимание, что സ
шире A
(примерно в 2,5 раза шире), аസി
почти равно 3 кодовым точкам ASCII фиксированной ширины!Однако не все малаяламские буквы такие широкие.Следующая буква в первом примере это U + 0D1F МАЛАЯЛАМСКОЕ ПИСЬМО TTA , которое гораздо менее широко:
>>> print u'\u0d38\nA..\n\u0d1f\nB..'
സ
A..
ട
B..
На практике я надеюсь, что разница не имеет значенияи вместо этого кодовые точки объединяются так, что вывод заканчивается примерно одинаковой ширины.
Далее, у малаялама есть и другие комбинирующие символы;Ваша первая строка имеет U + 0D4D ЗНАК МАЛАЯЛАМ ВИРАМА , который был объединен с предыдущей буквой TTA.
Диакритические знаки, в сочетании с предыдущей буквой, приводят к хаосу с шириной печати:
>>> print u'\u0d1f\nA..\n\u0d4d\nB..\n\u0d1f\u0d4d\nAB.'
ട
A..
്
B..
ട്
AB.
Буква TTA такая же широкая, как и буква ASCII, и когда вы добавляете знак virama, ширина фактически не меняется.
Вы можете приблизить размеры, посмотрев накодовая точка Unicode общие категории .Функция unicodedata.category()
дает вам категорию в виде строки:
>>> import unicodedata
>>> unicodedata.category(u'\u0d38')
'Lo'
>>> unicodedata.category(u'\u0d3f')
'Mc'
>>> unicodedata.category(u'\u0d4d')
'Mn'
Буква SA - это Lo
(Буква, другая), знак гласной - Mc
(Отметка(объединение пробелов), и знак virama равен Mn
(Марк, без пробелов).
>>> categories = {}
>>> for c in a[0]:
... cat = unicodedata.category(c)
... categories[cat] = categories.get(cat, 0) + 1
...
>>> categories
{'Lo': 4, 'Mn': 1, 'Mc': 4, 'Zs': 1}
Итак, для первой строки есть 4 буквы, 4 знака объединения и один знак гласного.Категория Zs
(Разделитель, пробел) предназначена для символа пробела ' '
ASCII.
Можем ли мы получить лучшую предсказуемую ширину, если пропустить символы Mc
и Mn
?Строка a[0]
будет иметь ширину 5 символов (4 раза Lo
и 1 пробел):
>>> print a[0] + '\nABCDE.'
സി ട്രീമിം
ABCDE.
В браузере это выглядит недостаточно близко, но в моем окне терминала iTerm это выглядит такэто:
സി ട്രീമിം and ABCDE.
, with the capital letters in the second string producing roughly the same width on the screen as the first line.">
Чтобы выровнять линии, вам нужно рассчитать правильную ширину для ваших строк, чтобы добавить дополнительные пробелы для разницыв ширину дисплея и количество кодовых точек:
import unicodedata
def malayalam_width(s):
return sum(1 for c in s if unicodedata.category(c)[0] != 'M')
form = u'{:<{width}}{:<3}({})'
for line in a:
line = line[:12]
adjust = len(line) - malayalam_width(line)
print form.format(line, 1, 2, width=15 + adjust)
Это улучшает вывод много уже:
Кажется, что более широкие буквы все-таки имеют значение.Вы должны были бы вручную добавить дополнительную ширину для тех, чтобы получить лучший результат;с отображением буквы на скорректированную ширину вы можете сделать так, чтобы выровнять немного лучше.Однако ширина кодовой точки определяется шрифтом, который вы используете, и я не уверен, насколько легко найти шрифт, который использует одинаковую ширину для всех букв малаялам.
Я считаю, что гораздо проще использоватьтабуляция, используя
form = u'{:<{width}}\t{:<3}({})'
for line in a:
line = line[:12]
adjust = len(line) - malayalam_width(line)
print form.format(line, 1, 2, width=12 + adjust)
Теперь числа выстраиваются в линию:
Вам необходимо продолжать регулировку ширины;в противном случае вы окажетесь в неправильной табуляции и остановитесь в половине случаев.
Предостережение: я совсем не знаком со сценарием малаялам, и я уверен, что пропустил тонкости о том, как различные буквы, гласные знакии диакритические знаки взаимодействуют.Кто-то, кто более знаком со сценарием и кодовыми точками Unicode, вероятно, сможет создать лучшую функцию приближения ширины, чем я представил здесь.
Я также проигнорировал кодовые точки 2 U + 200C ZERO WIDTH NON-JOINER , которые в настоящее время присутствуют в вашей последней строке;Вы можете удалить их из своих данных.Как следует из названия, он также не имеет ширины.