Python3 и объединение диакритических знаков - PullRequest
0 голосов
/ 20 февраля 2019

У меня была проблема с Unicode в python3, и я не могу понять, почему это происходит.

symbol= "ῇ̣"
print(len(symbol))
>>>>2

Это письмо происходит от слова: ἐ̣ν̣τ̣ῇ̣ [αὐτ] ​​ῇ, где я объединяю диакритические знаки.Я хочу провести статистический анализ в Python 3 и сохранить результаты в базе данных, дело в том, что я также сохраняю позицию (индекс) персонажа в тексте.Приложение базы данных правильно считает символьную переменную в примере как односимвольную, тогда как Python считает ее как две - отбрасывая всю индексацию.

Проект требует от меня соблюдения диакритических знаков, чтобы я мог 'просто игнорируйте их или сделайте .replace("combining diacritical mark","") в строке.

Поскольку в Python3 по умолчанию для строк используется Юникод, я немного удивлен этим.

Я пытался использовать метод base(), strip() и strip_length() от греческого акцентуации: https://pypi.org/project/greek-accentuation/, но это тоже не помогает.

Требования к проектуявляются:

  • Определение алфавита, принадлежащего символу (ОК)
  • Сохранение позиций строк (необходимо для выделения в базе данных) (NotOK)
  • Умениеобрабатывать несколько языков / алфавитов, смешанных в одной строке.(ОК)
  • Итерация по CSV-вводу.(ОК)
  • Игнорировать набор предопределенных строк (ОК)
  • Игнорировать набор строк, соответствующих определенным условиям (ОК)

Это упрощенный код для этогопроект:

# -*- coding: utf-8 -*-
import csv
from alphabet_detector import AlphabetDetector
ad = AlphabetDetector()
with open("tbltext.csv", "r", encoding="utf8") as txt:
    data = csv.reader(txt)
    for row in data:
        text = row[1]
        ### Here I have some string manipulation (lowering everything, replacing the predefined set of strings by equal-length '-',...)
        ###then I use the ad-module to detect the language by looping over my characters, this is where it goes wrong.
        for letter in text:
            lang = ad.detect_alphabet(letter)

Если я использую слово: ἐ̣ν̣τ̣ῇ̣[αὐτ]ῇ в качестве примера с forloop;мой результат:

>>> word = "ἐ̣ν̣τ̣ῇ̣[αὐτ]ῇ"
>>> for letter in word:
...     print(letter)
...
ἐ
̣
ν
̣
τ
̣
ῇ
̣
[
α
ὐ
τ
]
ῇ

Как я могу заставить Python видеть буквы с объединяющей диакритической меткой в ​​одной букве вместо того, чтобы печатать букву и диакритическую метку отдельно?

1 Ответ

0 голосов
/ 20 февраля 2019

Строка имеет длину 2, так что это правильно: две кодовые точки:

>>> list(hex(ord(c)) for c in symbol)
['0x1fc7', '0x323']
>>> list(unicodedata.name(c) for c in symbol)
['GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI', 'COMBINING DOT BELOW']

Поэтому вам не следует использовать len для подсчета символов.

Вы можете посчитатьсимволы, которые не объединяются, поэтому:

>>> import unicodedata
>>> len(''.join(ch for ch in symbol if unicodedata.combining(ch) == 0))
1

From: Как получить "видимую" длину строки объединения Unicode в Python? (но я перенес ее наpython3).

Но это тоже не оптимальное решение, в зависимости от объема подсчета символов .Я думаю, что в вашем случае этого достаточно, но шрифты могут объединять символы в лигатуры .На некоторых языках это визуально новые (и очень разные) символы (и не похожие на лигатуры в западных языках).

В качестве последнего комментария: я думаю, что вы должны нормализовать строки.С приведенным выше кодом, в этом случае это не имеет значения, но в других случаях вы можете получить другие результаты.Особенно, если кто-то использовал символы совместимости (например, mu для юнитов или Eszett вместо настоящих греческих символов).

...