Python возвращает неправильную длину строки при использовании специальных символов

У меня есть строка «aalt», что я хочу получить длину манипуляции на основе позиций персонажа и так далее. Проблема в том, что первый ë пересчитывается дважды, или я полагаю, что ë находится в положении 0 и 'находится в позиции 1.

Есть ли какой-либо возможный способ в Python иметь такой символ, как «быть представленным как 1?

Я использую кодировку UTF-8 для фактического кода и веб-страницы, на которую она выводится.

Редактирование: Просто некоторые сведения о том, зачем мне это нужно. Я работаю над проектом, который переводит английский язык в Сенеку (форма индейского языка), и ë проявляется совсем немного. Некоторые правила перезаписи для определенных слов требуют знания положения букв (самого себя и окружающих букв) и других характеристик, таких как акценты и другие диакритические знаки.

  • Сервер кометы Python
  • Двоичный набор двоичных файлов в Python?
  • Вызов функций с несколькими аргументами при использовании Groupby
  • Последовательное получение ImportError: не удалось импортировать настройки «myapp.settings»
  • Увеличение яркости изображения без переполнения
  • Does, With open () не работает с python 2.6
  • Совместимость с PHP preg_match в Python
  • многопоточные процессы python для запуска исполняемых файлов
  • 5 Solutions collect form web for “Python возвращает неправильную длину строки при использовании специальных символов”

    UTF-8 – это кодировка юникода, которая использует более одного байта для специальных символов. Если вам не нужна длина закодированной строки, просто декодируйте ее и используйте len() для объекта unicode (а не str объект!).

    Вот некоторые примеры:

     >>> # creates a str literal (with utf-8 encoding, if this was >>> # specified on the beginning of the file): >>> len('ë́aúlt') 9 >>> # creates a unicode literal (you should generally use this >>> # version if you are dealing with special characters): >>> len(u'ë́aúlt') 6 >>> # the same str literal (written in an encoded notation): >>> len('\xc3\xab\xcc\x81a\xc3\xbalt') 9 >>> # you can convert any str to an unicode object by decoding() it: >>> len('\xc3\xab\xcc\x81a\xc3\xbalt'.decode('utf-8')) 6 

    Разумеется, вы также можете получить доступ к одиночным символам в объекте unicode как это basestring бы в объекте str (они оба наследуются от basestring и поэтому имеют одинаковые методы):

     >>> test = u'ë́aúlt' >>> print test[0] ë 

    Если вы разрабатываете локализованные приложения, обычно рекомендуется использовать только объекты unicode внутри, путем декодирования всех вводимых вами данных. После завершения работы вы можете снова закодировать результат как «UTF-8». Если вы придерживаетесь этого принципа, вы никогда не увидите, что ваш сервер сбой из-за любого внутреннего UnicodeDecodeError вы могли бы получить иначе;)

    PS: Обратите внимание, что тип данных str и unicode значительно изменился в Python 3. В Python 3 есть только строки unicode и строки простого байта, которые больше нельзя смешивать. Это должно помочь избежать общих ошибок с обработкой unicode …

    С уважением, Кристоф

    Проблема в том, что первый ë пересчитывается дважды, или я полагаю, что ë находится в положении 0 и 'находится в позиции 1.

    Да. Вот как код указывает на Unicode. В общем, вы можете попросить Python преобразовать букву и отдельную «комбинирующую» диакритическую метку, такую ​​как U + 0301 COMBINING ACUTE ACCENT, используя нормализацию Unicode:

     >>> unicodedata.normalize('NFC', u'a\u0301') u'\xe1' # single character: á 

    Однако в Unicode нет единого символа для «e с диарезисом и острым акцентом», потому что ни один язык в мире никогда не использовал букву «ë». (Транслитерация пиньинь имеет «u с диарезисом и острым акцентом», но не «e».) Следовательно, поддержка шрифтов оставляет желать лучшего; во многих случаях это очень плохо отражается и является грязным блобом в моем веб-браузере.

    Чтобы определить, где «редактируемые точки» в строке кодовых точек Юникода – это сложная работа, требующая довольно много знаний о языках в языках. Это часть вопроса о «сложном текстовом макете», области, которая также включает в себя такие вопросы, как двунаправленный текст и контекстуальное шейпинг и лигатуры. Для выполнения сложного текстового макета вам понадобится библиотека, такая как Uniscribe в Windows или Pango вообще (для которой существует интерфейс Python).

    Если, с другой стороны, вы просто хотите полностью игнорировать все комбинации символов при выполнении счета, вы можете легко избавиться от них:

     def withoutcombining(s): return ''.join(c for c in s if unicodedata.combining(c)==0) >>> withoutcombining(u'ë́aúlt') '\xeba\xfalt' # ëaúlt >>> len(_) 5 

    Лучшее, что вы можете сделать, это использовать unicodedata.normalize() чтобы разложить символ, а затем отфильтровать акценты.

    Не забудьте использовать в коде unicode и Unicode.

    Вы сказали: у меня есть строка: «Я хочу получить длину манипуляции на основе позиций персонажа и так далее. Проблема в том, что первый ë пересчитывается дважды, или я полагаю, что ë находится в положении 0 и 'находится в позиции 1.

    Первый шаг в работе над любой проблемой Unicode – это точно знать, что находится в ваших данных; не догадываюсь. В этом случае ваша догадка верна; это не всегда будет.

    «Именно то, что находится в ваших данных»: используйте встроенную функцию repr () (для большего количества вещей помимо юникода). Полезное преимущество показа результата repr () в вашем вопросе заключается в том, что у ответчиков есть то, что у вас есть. Обратите внимание, что ваш текст отображается только в 4-х позициях вместо 5 с некоторыми браузерами / шрифтами – «e» и его диакритики, а «a» искажены вместе в одной позиции.

    Вы можете использовать функцию unicodedata.name (), чтобы рассказать вам, что представляет собой каждый компонент.

    Вот пример:

     # coding: utf8 import unicodedata x = u"ë́aúlt" print(repr(x)) for c in x: try: name = unicodedata.name(c) except: name = "<no name>" print "U+%04X" % ord(c), repr(c), name 

    Результаты:

     u'\xeb\u0301a\xfalt' U+00EB u'\xeb' LATIN SMALL LETTER E WITH DIAERESIS U+0301 u'\u0301' COMBINING ACUTE ACCENT U+0061 u'a' LATIN SMALL LETTER A U+00FA u'\xfa' LATIN SMALL LETTER U WITH ACUTE U+006C u'l' LATIN SMALL LETTER L U+0074 u't' LATIN SMALL LETTER T 

    Теперь прочитайте ответ @ bobince 🙂

    какую версию Python вы используете? Python 3.1 не имеет этой проблемы.

     >>> print(len("ë́aúlt")) 6 

    С уважением Джуди

    Python - лучший язык программирования в мире.