Страницы

Поиск по вопросам

среда, 20 февраля 2019 г.

Длина строки считается неверно: unicode в python 2.x

Вычисляю длину строки. Но длина строки (наверное), считается удвоенной для русских символов. Для цифр -- нет. Например:
len("ул Весёлая") == 1 + 2 * 9 // (Пробел + русские символы (*2)) len("ул Весёлая 71") == 1 + 2 * 9 + 1 + 3 // (Пробел + русские символы (*2) + пробел + 2 цифры)
Есть ли функция в питоне, которая считает истиную длину строки, а не количество байтов (считается, наверное, именно кол-во байтов).


Ответ

Проблема не возникает, если использовать правильные(unicode) строки:
>>> print(len('ул Весенняя 13')) 24 >>> print(len(u'ул Весенняя 13')) 14
Можно самостоятельно декодировать простые строки:
>>> print(len('ул Весенняя 13'.decode("utf-8"))) 14

В python3 нет такой проблемы, потому что строки по умолчанию в utf-8:
>>> print(len('ул Весенняя 13')) 14 >>> print(len(u'ул Весенняя 13')) 14

В общем случае(полный набор символов unicode) задача найти длину строки не является тривиальной.
Во первых, нужно определиться с самим термином - что понимать под длиной строки?
Варианты:
количество байт в utf-8 представлении (24 выше) количество unicode символов (14 выше) можно посчитать, как количество всех байт, кроме диапазона (0x80-0xBF). количество видимых знаков количество занятых знакомест Нужно исключить диакритику и прочие символы, не занимающие места
Положение усугубляется ещё и тем, что одни и те же строки могут быть закодированы разными последовательностями unicode codepoints. Для определённости можно "нормализовать" строку, например, с помощью unicodedata.normalize('NFC', ustr)
>>> len(regex.findall(ur'[\0-\u02FF\u0370-\u1DBF\u1E00-\u20CF\u2100-\uD7FF\uDC00-\uFE1F\uFE30-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF][\u0300-\u036F\u1DC0-\u1DFF\u20D0-\u20FF\uFE20-\uFE2F]', unicodedata.normalize('NFC', u'Z͑ͫ̓ͪ̂ͫ̽͏̴̙A̴̵̜̰͔ͫ͗͢L̠ͨͧͩ͘G̴̻͈͍̑͗̎̅͛́Ǫ̵̹̻̝̳͂̌̌͘!̿̋ͥͥ̂ͣ̐́́͞'))) 6

Комментариев нет:

Отправить комментарий