【问题标题】:Remove accent marks from characters while preserving other diacritics从字符中删除重音符号,同时保留其他变音符号
【发布时间】:2016-06-26 19:27:46
【问题描述】:

在一些用拉丁文和西里尔文书写的斯拉夫语言中,上升和下降的重音符号仅用于在上下文中消除歧义,即不一致,仅用于元音。

我想要一个 Python 代码或库删除元音中的重音和重音,同时保留其他变音符号。

例如:
жѝзнеспосо́бный -> жизнеспособный
сè се фаќа -> се се фаќа强>
kȕćica -> kućica

如果有帮助,这里是斯拉夫语言中所有实际(即非重音)西里尔字母的完整列表,包括带有变音符号的字母:

абвгдежзиклмнпорстуфхцшєґіїёыіўщъьюяйјњљџђћз́с́ќѓѕ

注意:

  1. їёыіўй 是元音,即使去掉了重音符号和重音符号,也应保留其变音符号。但这种情况非常罕见,甚至不可能,我们可以忽略这种情况。

  2. з́с́ќѓ是辅音,如拉丁语ćǵśź。他们应该保留他们的重音符号——他们不会为了发音或消除歧义而添加任何符号。

  3. 在精确的正式映射是官方的字母表中,带有重音的拉丁辅音的西里尔字母等价物不一定有重音。 (也许有帮助。)

  4. 双锐和双重是低优先级。

这些字符的背景阅读:
https://en.wikipedia.org/wiki/I_with_grave_(Cyrillic)#East_Slavic_languages https://en.wikipedia.org/wiki/Shtokavian#Accentuation
https://en.wikipedia.org/wiki/Pitch_accent#Serbo-Croatian
https://en.wikipedia.org/wiki/Bulgarian_alphabet#.D0.8D
https://en.wikipedia.org/wiki/Macedonian_alphabet#Accented_letters

类似问题:
Removing accents/diacritics from string while preserving other special chars (tried mb_chars.normalize and iconv)
How to remove accent in Python 3.5 and get a string with unicodedata or other solutions?

【问题讨论】:

  • 我认为链接问题“如何在 Python 3.5 中删除重音...”中的翻译方法将是您要求的最简单的方法。您只需要定义要将哪些字符翻译成其他字符。
  • str.translate 对此不起作用,因为о́ 不是/没有单个代码点。

标签: python unicode internationalization nlp cyrillic


【解决方案1】:

如果您可以列出相应的对,则不需要库。

>>> unaccentify = {
...    'ѝ': 'и',
...    'о́': 'о'
... }

我打算为此建议 string.translate,但不幸的是它不起作用,因为 о́ 没有单个代码点。因此,我们确保左侧字符是 NFKC 规范化的:

>>> import unicodedata
>>> unaccentify = {unicodedata.normalize('NFKC', i):j for i, j in unaccentify.items()}

然后我们对所有可能的替换字母进行正则表达式:

>>> import re
>>> pattern = re.compile('|'.join(unaccentify))

然后使用pattern.sub 进行替换,从表格中查找非重音字符。但首先我们需要规范化源字符串:

>>> def replacer(match):
...     return unaccentify[match.group(0)]
...
>>> source = unicodedata.normalize('NFKC', 'жѝзнеспосо́бный')
>>> pattern.sub(replacer, source)
'жизнеспособный'

【讨论】:

  • 好点,只有 5 个真正的元音。另一个想法是使用现有库(有很多)转换为拉丁语(因为可以可靠地转换元音),然后使用现有库(有很多)删除变音符号,然后使用第一个库转换回西里尔字母。我希望没有单个代码点(即,重音是单独编码的)这一事实可以使它变得容易。
  • 可以通过NFKD规范化将重音与字母分开,但那样做会更有效,因为ѓ会变成г + 结合尖锐的口音。
【解决方案2】:

这是受上一个答案的启发(映射字典兼容),但使其更完整且无需正则表达式:

import unicodedata

ACCENT_MAPPING = {
    '́': '',
    '̀': '',
    'а́': 'а',
    'а̀': 'а',
    'е́': 'е',
    'ѐ': 'е',
    'и́': 'и',
    'ѝ': 'и',
    'о́': 'о',
    'о̀': 'о',
    'у́': 'у',
    'у̀': 'у',
    'ы́': 'ы',
    'ы̀': 'ы',
    'э́': 'э',
    'э̀': 'э',
    'ю́': 'ю',
    '̀ю': 'ю',
    'я́́': 'я',
    'я̀': 'я',
}
ACCENT_MAPPING = {unicodedata.normalize('NFKC', i): j for i, j in ACCENT_MAPPING.items()}


def unaccentify(s):
    source = unicodedata.normalize('NFKC', s)
    for old, new in ACCENT_MAPPING.items():
        source = source.replace(old, new)
    return source

请注意,这里不关心速度。

不过,我还没有检查所有字符。如果发现奇怪的东西会更新答案。

【讨论】:

    猜你喜欢
    • 2010-10-06
    • 1970-01-01
    • 2015-08-30
    • 2010-09-19
    • 2012-12-10
    • 2022-01-03
    相关资源
    最近更新 更多