oro*_*ome 11 python unicode python-2.7
如果我有一个包含组合字符的Python Unicode字符串,则len
报告的值与"看到"的字符数不对应.
例如,如果我有结合overlines的字符串,并强调如u'A\u0332\u0305BC'
,len(u'A\u0332\u0305BC')
报告5; 但显示的字符串长度只有3个字符.
如何获得"可见" - 即用户看到的字符串占用的不同位置的数量 - 包含Python中组合字形的Unicode字符串的长度?
如果您有支持匹配字素的正则表达式风格,您可以使用\X
虽然默认的 Python re 模块不支持\X
,但 Matthew Barnett 的regex 模块支持:
>>> len(regex.findall(r'\X', u'A\u0332\u0305BC'))
3
Run Code Online (Sandbox Code Playgroud)
在 Python 2 上,您需要u
在模式中使用:
>>> regex.findall(u'\\X', u'A\u0332\u0305BC')
[u'A\u0332\u0305', u'B', u'C']
>>> len(regex.findall(u'\\X', u'A\u0332\u0305BC'))
3
Run Code Online (Sandbox Code Playgroud)
该unicodedata
模块combining
具有可用于确定单个字符是否为组合字符的功能。如果它返回,0
您可以将该字符算作非组合字符。
import unicodedata
len(u''.join(ch for ch in u'A\u0332\u0305BC' if unicodedata.combining(ch) == 0))
Run Code Online (Sandbox Code Playgroud)
或者,稍微简单一点:
sum(1 for ch in u'A\u0332\u0305BC' if unicodedata.combining(ch) == 0)
Run Code Online (Sandbox Code Playgroud)
编辑:正如评论中所指出的,除了组合标记之外,还有一些代码点可以修改字符,而不是本身不应该在计数中的字符。这是上述内容的更强大的版本:
modifier_categories = set(['Mc', 'Mn'])
sum(1 for ch in u'A\u0332\u0305BC' if unicodedata.category(ch) not in modifier_categories)
Run Code Online (Sandbox Code Playgroud)
我们可以使用另一个 Python 技巧,利用True==1
和来使事情变得更简单False==0
:
sum(unicodedata.category(ch) not in modifier_categories for ch in u'A\u0332\u0305BC')
Run Code Online (Sandbox Code Playgroud)