【问题标题】:How do I iterate through unicode symbols, not bytes in python?如何遍历 unicode 符号,而不是 python 中的字节?
【发布时间】:2014-01-14 02:09:03
【问题描述】:

鉴于像u'кни́га' 这样的重音unicode 词,我需要去除锐音(@9​​87654323@),并将重音格式更改为u'кни+га',其中'+' 表示前一个字母的锐音。

我现在做的是使用锐化符号和非锐化符号字典:

accented_list = [u'я́', u'и́', u'ы́', u'у́', u'э́', u'а́', u'е́', u'ю́', u'о́']
regular_list = [u'я', u'и', u'ы', u'у', u'э', u'а', u'е',  u'ю', u'о']
accent_dict = dict(zip(accented_list, regular_list))

我想做这样的事情:

def changeAccentFormat(word):
  for letter in accent_dict:
    if letter in word:
      its_index = word.index(letter)
      word = word[:its_index + 1] + u'+' + word[its_index + 1:]
  return word

但它当然不能按预期工作。我注意到这段代码:

>>> word = u'кни́га'
>>> for letter in word:
...     print letter

给予

к
н
и                                                                                                                                                                                  
´   

г
а

(好吧,我没想到会出现空白符号,但尽管如此)。所以我想知道,产生[u'к', u'н', u'и́', u'г', u'а'] 的最简单方法是什么?或者也许没有它有什么方法可以解决我的问题?

【问题讨论】:

  • >>> len(u'кни́га') 6 Python 只会这样对待它们
  • 定义“unicode 符号”。 Python 不会遍历字节,它会遍历代码点(只要您留在 BMP 内或使用 >= 3.3 的版本)。这是一个有意义的抽象,尽管并不总是你想要的。根据您是否有意在所需输出中省略了“г”上的重音,您似乎想要字素簇或删除组合字符。或许您可以描述一下您的用例,以便我们帮助您选择?
  • @delnan,急性在 'и́' 字母上,并且仍然出现在所需的输出中:) 但是我明白了,我会编辑问题
  • 天啊!好吧,缩小范围,您应该研究的概念是字素簇。
  • "symbol" 来自 ASCII 思维。你想数字形吗? utf8everywhere.org各种解释

标签: python unicode python-unicode


【解决方案1】:

您可以使用regex 模块生成[u'к', u'н', u'и́', u'г', u'а']。

这是每个用户感知到的字符的单词:

>>> import regex
>>> word = u'кни́га'
>>> len(word)
6
>>> regex.findall(r'\X', word)
['к', 'н', 'и́', 'г', 'а']
>>> len(regex.findall(r'\X', word))
5

【讨论】:

    【解决方案2】:

    首先,关于迭代字符而不是字节,你已经做对了 - 你的 word 是一个 unicode 对象,而不是一个编码的字节串。

    现在,对于 Unicode 中的组合字符:

    对于许多包含组合字符的字符,有一种 composed 和 decomposed 的书写形式,composition 是一个代码点,decomposed 是两个(或更多?)代码点:

    见U+00E7、U+0063和U+0327

    所以在 Python 中,您可以编写任何一种形式,它会在显示时组合成相同的字符:

    >>> combining_cedilla = u'\u0327'
    >>> c_with_cedilla = u'\u00e7'
    >>> letter_c = u'\u0063'
    >>>
    >>> print c_with_cedilla
    ç
    >>> print letter_c + combining_cedilla
    ç
    

    为了在组合形式和分解形式之间进行转换,可以使用unicodedata.normalize():

    >>> import unicodedata
    >>> comp = unicodedata.normalize('NFC', letter_c + combining_cedilla)
    >>> decomp = unicodedata.normalize('NFD', c_with_cedilla)
    >>>
    >>> print comp
    ç
    >>> print decomp
    ç
    

    (NFC 代表“范式 C”(组合),NFD 代表“范式 D”(分解)。

    尽管它们仍然是不同的形式 - 一种由一个代码点组成,另一种由两个代码点组成:

    >>> comp == decomp
    False
    >>> len(comp)
    1
    >>> len(decomp)
    2
    

    但是,在您的情况下,小写 и 似乎根本没有带有重音符号的组合字符(и with an accent grave 有一个)

    【讨论】:

      【解决方案3】:

      Acutes 由代码点 301 COMBINING ACUTE ACCENT 表示,因此一个简单的字符串字符替换就足够了:

      >>>print u'кни́га'.replace(u'\u0301', "+")
      кни+га
      

      如果您遇到未使用组合重音编码的重音字符,unicodedata.normalize 应该可以解决问题

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-02-21
        • 2016-02-20
        • 2013-12-19
        • 2017-05-03
        • 2021-12-17
        • 1970-01-01
        • 2010-09-18
        • 2012-07-12
        相关资源
        最近更新 更多