Alb*_*ert 3 python unicode unicode-normalization python-3.x
例如,对于字符"a",我想获取一个字符串(字符列表),例如"aàáâãäå???"(不确定示例列表是否完整...)(基本上是所有带有name的unicode字符"Latin Small Letter A with *")。
有没有通用的方法可以做到这一点?
我要求使用Python,但是如果答案更通用,那也很好,尽管在任何情况下我都希望Python代码片段。Python> = 3.5很好。但是我想您需要访问Unicode数据库,例如Python模块unicodedata,我比其他外部数据源更喜欢它。
我可以想象这样的解决方案:
def get_variations(char):
import unicodedata
name = unicodedata.name(char)
chars = char
for variation in ["WITH CEDILLA", "WITH MACRON", ...]:
try:
chars += unicodedata.lookup("%s %s" % (name, variation))
except KeyError:
pass
return chars
Run Code Online (Sandbox Code Playgroud)
首先,获取包含变音字符的Unicode集合;它们是连续的,所以这很简单,例如:
# Unicode combining diacritical marks run from 768 to 879, inclusive
combining_chars = ''.join(map(chr, range(768, 880)))
Run Code Online (Sandbox Code Playgroud)
现在定义一个试图用基本ASCII字符组成每个函数的函数;当组成的标准格式的长度为1(意味着ASCII +组合成为单个Unicode序数)时,将其保存:
import unicodedata
def get_unicode_variations(letter):
if len(letter) != 1:
raise ValueError("letter must be a single character to check for variations")
variations = []
# We could just loop over map(chr, range(768, 880)) without caching
# in combining_chars, but that increases runtime ~20%
for combiner in combining_chars:
normalized = unicodedata.normalize('NFKC', letter + combiner)
if len(normalized) == 1:
variations.append(normalized)
return ''.join(variations)
Run Code Online (Sandbox Code Playgroud)
这样的优点是,无需尝试在unicodedata数据库中手动执行字符串查找,也不需要对组合字符的所有可能描述进行硬编码。组成单个字符的所有内容都将包括在内;在我的机器上执行检查的运行时间不到50 µs,因此,如果您不经常执行此检查,则成本是合理的(functools.lru_cache如果您打算使用相同的参数重复调用它并希望避免重新计算,则可以进行修饰。每次)。
如果你想获得的一切建造这些人物之一了,更详尽的搜索可以找到它,但它会需要更长的时间(functools.lru_cache将在附近强制性,除非它只会被调用每一次的说法):
import functools
import sys
import unicodedata
@functools.lru_cache(maxsize=None)
def get_unicode_variations_exhaustive(letter):
if len(letter) != 1:
raise ValueError("letter must be a single character to check for variations")
variations = []
for testlet in map(chr, range(sys.maxunicode)):
if letter in unicodedata.normalize('NFKD', testlet) and testlet != letter:
variations.append(testlet)
return ''.join(variations)
Run Code Online (Sandbox Code Playgroud)
这将查找分解为包含目标字母的形式的任何字符;这确实意味着第一次搜索大约需要三分之一的时间,并且结果包含的内容实际上并不是字符的修改版本(例如'L',的结果将包括?,而实际上不是“修改过的” 'L') ,但请尽可能详尽。