Строка с выравниванием по правому краю, содержащая тайские символы

Я хотел бы выровнять по правому краю строки, содержащие тайские символы (тайский рендеринг не работает слева направо, но также может идти вверх и вниз).

Например, для строк ไป (два символа, длина 2) и ซื้อ (четыре символа, длина 2) я хочу получить следующий вывод (длина 5):

...ไป

...ซื้อ

Наивный

print 'ไป'.decode('utf-8').rjust(5)

print 'ซื้อ'.decode('utf-8').rjust(5)

однако, соответственно производить

...ไป

.ซื้อ

Любые идеи, как добраться до нужного форматирования?

РЕДАКТИРОВАТЬ: Учитывая строку тайских символов tc, я хочу определить, сколько [мест/полей/позиций/как бы вы это ни называли] использует строка. Это не то же самое, что len(tc); len(tc) обычно больше, чем количество используемых мест. Второе слово дает len(tc) = 4, но имеет длину 2/использует 2 позиции/использует 2 позиции.


person user1864353    schedule 29.11.2012    source источник
comment
Какой язык/среду вы используете?   -  person isturdy    schedule 30.11.2012
comment
неясно, о каком программном обеспечении/языке/среде этот вопрос.   -  person owagh    schedule 30.11.2012
comment
Выглядит прекрасно. import antigravity - Это Питон.   -  person Anuj Gupta    schedule 30.11.2012
comment
Язык, среда? У меня MacBook Air, Python 2.7... это среда?   -  person user1864353    schedule 30.11.2012


Ответы (4)


Причина

Тайский шрифт содержит обычные символы (положительная ширина продвижения) и метки без пробелов (нулевая ширина продвижения).

Например, в слове ซื้อ:

  1. первый символ - начальный согласный "SO SO",
  2. затем у него есть знак гласной SARA UUE,
  3. затем отметка тона MAI THO,
  4. а затем последний псевдосогласный O ANG

Проблема в том, что символы ##2 и 3 в приведенном выше списке являются нулевыми.
Другими словами, они не делают строку "шире".
В других случаях слова, ซื้อ ("купить") и ซอ ("скрипка") будут иметь равную ширину двух знаков (но длину строки 4 и 2 соответственно).

Решение

Чтобы вычислить «настоящую» длину строки, нужно пропустить символы нулевой ширины.

Специфично для Python

Модуль unicodedata обеспечивает доступ к базе данных символов Unicode (UCD), которая определяет свойства символов. для всех символов Юникода. Данные, содержащиеся в этой базе данных, собраны из UCD версии 8.0.0.

Метод unicodedata.category(unichr) возвращает один из следующих Общие значения категорий:

  • "Lo" для обычного персонажа;
  • "Mn" для меток без пробелов нулевой ширины;

Остальное очевидно, просто отфильтруйте последние.


Дополнительная информация:

person bytebuster    schedule 13.02.2016

Я думаю, что вы хотите спросить, как определить «истинное» количество символов в เรือ, ไป, ซื้อ и т. д. (3,2 и 2 соответственно)

К сожалению, вот как Python интерпретирует эти символы:

ไป

>>> 'ไป'
'\xe0\xb9\x84\xe0\xb8\x9b'
>>> len('ไป')
6
>>> len('ไป'.decode('utf-8'))
2

ซื้อ

>>> 'ซื้อ'
'\xe0\xb8\x8b\xe0\xb8\xb7\xe0\xb9\x89\xe0\xb8\xad'
>>> len('ซื้อ')
12
>>> len('ซื้อ'.decode('utf-8'))
4

เรือ

>>> 'เรือ'
'\xe0\xb9\x80\xe0\xb8\xa3\xe0\xb8\xb7\xe0\xb8\xad'

>>> len('เรือ')
12
>>> len('เรือ'.decode('utf-8'))
4

Нет реальной корреляции между количеством отображаемых символов и количеством фактических (с точки зрения Python) символов, составляющих строку.

Я не могу придумать очевидный способ сделать это. Однако я нашел эту библиотеку, которая может вам помочь. (Вам также потребуется установить некоторые предварительные требования.

person Anuj Gupta    schedule 29.11.2012
comment
Спасибо, Анудж Гупта. Читая предложенные библиотечные функции, мне не ясно, будут ли они работать для тайского языка; их внимание сосредоточено на восточноазиатских языках. Я думаю, я просто сам реализую такую ​​функцию истинной длины, классифицируя соответствующие представления юникода. - person user1864353; 30.11.2012

Похоже, что функция rjust() вам не подойдет и вам нужно будет самостоятельно подсчитать количество ячеек в строке. Затем вы можете вставить необходимое количество пробелов перед строкой для достижения выравнивания

Кажется, ты знаешь тайский язык. Суммируйте количество согласных, предшествующих гласных, следующих за гласными и тайскую пунктуацию. Не считайте диакритические знаки и верхние и нижние гласные.

Что-то вроде (простите мой псевдо-код Python),

cells = 0

for i in range (0, len(string))
  if (string[i] == \xe31) or ((string[i] >= \xe34) and (string[i] <= \xe3a)) or ((string[i] >= \xe47) and (string[i] <= \xe4e))
     # do nothing
  else
     # consonant, preceding or following vowel or punctuation
     cells++
person koan    schedule 12.02.2016

Вот функция для вычисления длины тайской строки (количество символов, расположенных по горизонтали), на основе ответа bytebuster

import unicodedata


def get_thai_string_length(string):
    length = 0
    for c in string:
        if unicodedata.category(c) != 'Mn':
            length += 1
    return length

print(len('บอินทัช'))
print(get_thai_string_length('บอินทัช'))
person brunoob    schedule 17.10.2019