Как получить символ из строки - получить неправильный символ и неправильную длину строки - PullRequest
0 голосов
/ 15 октября 2019

Ниже python дает неправильную длину строки и неправильный символ.
Кто-нибудь здесь имеет какие-либо идеи?

>>> w ='lòng'
>>> w 
'lòng'
>>> print (w)
lòng
>>> len(w)
5
>>> for ch in w:
...     print (ch + "-") 
... 
l- 
o- 
- 
n- 
g- 
>>> 

Ответы [ 3 ]

3 голосов
/ 15 октября 2019

Проблема здесь в том, что в юникоде некоторые символы могут состоять из комбинаций других символов. В этом случае 'lòng' включает строчные буквы 'o' и серьезный акцент в качестве отдельных символов.

>>> import unicodedata as ud
>>> w ='lòng'
>>> for c in w:
...     print(ud.name(c))
... 
LATIN SMALL LETTER L
LATIN SMALL LETTER O
COMBINING GRAVE ACCENT
LATIN SMALL LETTER N
LATIN SMALL LETTER G

Это разложенная строка в кодировке Unicode, поскольку акцентированный 'o'раскладывается на два символа. Модуль unicodedata предоставляет функцию normalize для преобразования между декомпозированными и составными формами:

>>> for c in ud.normalize('NFC', w):
...     print(ud.name(c))
... 
LATIN SMALL LETTER L
LATIN SMALL LETTER O WITH GRAVE
LATIN SMALL LETTER N
LATIN SMALL LETTER G

Если вы хотите узнать, является ли строканормализуется к определенной форме, но на самом деле не хочет ее нормализовать и использует Python 3.8+, более эффективная функция unicodedata.is_normalized ( кредит пользователю Acumenus ):

>>> ud.is_normalized('NFC', w)
False
>>> ud.is_normalized('NFD', w)
True

Unicode HOWTO в документации Python содержит раздел сравнения строк , в котором это обсуждается более подробно.

1 голос
/ 15 октября 2019

Юникод обеспечивает большую гибкость при кодировании символа. В этом случае фактически состоит из 2 кодовых точек Unicode, одна для базового символа o и одна для знака ударения. Юникод также имеет символ, который представляет оба одновременно, и ему все равно, какой вы используете. Юникод обеспечивает большую гибкость при кодировании символа. Python включает в себя пакет unicodedata, который может обеспечить согласованное представление.

>>> import unicodedata
>>> w ='lòng'
>>> len(w)
5
>>> len(unicodedata.normalize('NFC', w))
4
0 голосов
/ 16 октября 2019

Проблема в том, что функция len и оператор in не работают относительно Unicode.

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

>>> w = 'Ꙝ̛͋ᄀᄀᄀ각ᆨᆨ?❤️??'
>>> len(w)
19
>>> import unicodedata
>>> len(unicodedata.normalize('NFC', w))
19
>>> # 19 is still wrong

Чтобы правильно выполнить эту задачу, вам нужно работать с графемами:

>>> from grapheme import graphemes
>>> w = 'Ꙝ̛͋ᄀᄀᄀ각ᆨᆨ?❤️??'
>>> len(list(graphemes(w)))
3
>>> # 3 is correct
>>> for g in graphemes(w):
...     print(g)
Ꙝ̛͋
ᄀᄀᄀ각ᆨᆨ
?❤️??

Также работает для вашего ввода w = 'lòng', правильно сегментируетв 4 без нормализации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...