【问题标题】:In Python 3, count Thai character positions在 Python 3 中,计算泰语字符位置
【发布时间】:2019-06-13 06:37:25
【问题描述】:

FIRST,我使用 Python 3 grapheme 库来解决我的问题。 (有关 grapheme 的更多信息,请参阅 this article)。但令我惊讶的是,如果没有专门的库,Python 3 就无法做到这一点……


我求助于 grapheme 是因为在多次网络搜索和阅读 StackOverflow 问题之后,我无法让 Python 3 在序列中返回正确数量的 字符位置泰语字符。

例如,这里是一个 UTF-8 泰语字符串:

thai_str = 'สีโชคดีเป็นสีชมพู สีโชคร้ายเป็นสีเหลืองและขาว'

我使用术语字符位置 来标识一行/字符串泰语字符中的单个位置。这是因为一个字符位置可能由一个泰语辅音加上,在某些情况下,该辅音上方或下方的元音或声调标记组成。辅音加上元音或音调标记上方/下方在 Unicode 字符串中占据单个 字符位置。 (一些泰语辅音也可能在其左侧、右侧或两者都有元音。这些元音占据它们自己的字符位置。)

例如,在从示例字符串生成的以下序列中,第 2 项和第 7 项是元音,第 10 项是音调标记。每个都使用 UTF-8 字符串中的单独字节,但不占用自己的字符位置。第 3 项和第 8 项是位于辅音左侧的元音,因此占据字符位置。

01: ส
02: ี
03: โ
04: ช
05: ค
06: ด
07: ี
08: เ
09: ป
10: ็
...
45: ว

当尝试确定示例字符串中的字符位置时,len(thai_str) 返回45。这是不正确的。我能够获得正确数量的字符位置的唯一方法是使用grapheme.length(thai_str) 来获得35

我还使用 encode 来获得以下信息:

b'\xe0\xb8\xaa\xe0\xb8\xb5\xe0\xb9\x82\xe0\xb8\x8a\xe0\xb8\x84\xe0\xb8\x94...

(计算似乎在每个泰语字符之前出现的xe0 实例感觉不是正确的方法......)

SO -- 在我的示例字符串中计算字符位置的唯一方法是使用 Python 3 库,例如 grapheme

【问题讨论】:

    标签: python python-3.x unicode thai grapheme


    【解决方案1】:

    更多解决方案,还可以通过UAX #29 中指定的扩展字形集群(“用户感知字符”):

    使用pyuegc

    from pyuegc import EGC  # pip install pyuegc
    
    egc = EGC('สีโชคดีเป็นสีชมพู สีโชคร้ายเป็นสีเหลืองและขาว')
    print(len(egc))
    # 35
    

    使用regex

    import regex  # pip install regex
    
    egc = regex.findall('\X', 'สีโชคดีเป็นสีชมพู สีโชคร้ายเป็นสีเหลืองและขาว')
    print(len(egc))
    # 35
    

    【讨论】:

      【解决方案2】:

      如果您想自己实现字素计数器,这不是唯一的方法,但它很复杂,您必须查阅https://unicode.org 规范才能正确使用。

      thai_str 不是 UTF-8 字符串,而是包含 Unicode 代码点的 Unicode 字符串。有不同的categories 代码点。计算字符位置所需的示例文本使用的两个类别是:

      • LoOther_Letter,其他字母,包括音节和表意文字;
      • Mn Nonspacing_Mark,非间距组合标记(零前进宽度)。

      如果您跳过计算 Nonspacing_Mark (Mn) 类别的代码点,您可以大致了解字形库在做什么:

      import unicodedata as ud
      
      thai_str = 'สีโชคดีเป็นสีชมพู สีโชคร้ายเป็นสีเหลืองและขาว'
      
      for cp in thai_str:
          print(f'{cp}\t{ud.category(cp)}\t{ud.name(cp)}')
      
      print(sum(1 for cp in thai_str if ud.category(cp)[0] != 'M'))
      

      输出:

      ส   Lo  THAI CHARACTER SO SUA
      ี   Mn  THAI CHARACTER SARA II
      โ   Lo  THAI CHARACTER SARA O
      ช   Lo  THAI CHARACTER CHO CHANG
      ค   Lo  THAI CHARACTER KHO KHWAI
      ด   Lo  THAI CHARACTER DO DEK
      ี   Mn  THAI CHARACTER SARA II
      เ   Lo  THAI CHARACTER SARA E
      ป   Lo  THAI CHARACTER PO PLA
      ็   Mn  THAI CHARACTER MAITAIKHU
      ...
      ว   Lo  THAI CHARACTER WO WAEN
      35
      

      【讨论】:

      • "thai_str 不是 UTF-8 字符串,而是包含 Unicode 码位的 Unicode 字符串。码位有不同的类别。"谢谢 - 内容丰富且乐于助人...
      • 对于那些运行 Python 版本
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-08
      相关资源
      最近更新 更多