Python:替换重音符号(é 到 e)、删除 [^a-zA-Z\d\s] 和 lower() 的有效方法 [重复]
Posted
技术标签:
【中文标题】Python:替换重音符号(é 到 e)、删除 [^a-zA-Z\\d\\s] 和 lower() 的有效方法 [重复]【英文标题】:Python: efficient method to replace accents (é to e), remove [^a-zA-Z\d\s], and lower() [duplicate]Python:替换重音符号(é 到 e)、删除 [^a-zA-Z\d\s] 和 lower() 的有效方法 [重复] 【发布时间】:2013-02-22 02:19:12 【问题描述】:使用 Python 3.3。我想做以下事情:
替换特殊的字母字符,例如 e 锐角 (é) 和 o 带基本字符(例如 ô 到 o)的抑扬符 (ô) 删除除字母数字和字母数字之间的空格以外的所有字符 字符 转换为小写这是我目前所拥有的:
mystring_modified = mystring.replace('\u00E9', 'e').replace('\u00F4', 'o').lower()
alphnumspace = re.compile(r"[^a-zA-Z\d\s]")
mystring_modified = alphnumspace.sub('', mystring_modified)
我该如何改进呢?效率是一个大问题,特别是因为我目前正在循环内执行操作:
# Pseudocode
for mystring in myfile:
mystring_modified = # operations described above
mylist.append(mystring_modified)
有问题的文件每个大约有 200,000 个字符。
【问题讨论】:
我无法发布答案,因为这个问题被错误地标记为重复,这绝对不是,但也许我会设法将我的答案放在评论中。提供from unidecode import unidecode
,工作将由''.join(c for c in unidecode(mystring).lower() if ord(c) in range(97,123) or ord(c)==32).lstrip().rstrip()
完成。不需要正则表达式。
【参考方案1】:
>>> import unicodedata
>>> s='éô'
>>> ''.join((c for c in unicodedata.normalize('NFD', s) if unicodedata.category(c) != 'Mn'))
'eo'
也可以查看unidecode
Unidecode 提供的是一条中间道路:函数 unidecode() 需要 Unicode 数据并尝试用 ASCII 字符(即 在 0x00 和 0x7F 之间普遍可显示的字符),其中 选择两个字符集之间的映射时采取的折衷方案 接近使用美式键盘的人的选择。
生成的 ASCII 表示的质量各不相同。对于语言 西方起源它应该介于完美和良好之间。在另一 手写音译(即用罗马字母传达 其他书写系统中文本所表达的发音)的 中文、日文或韩文等语言是一个非常复杂的问题,而且 这个库甚至没有尝试解决它。它在 上下文无关的逐字符映射。所以一个很好的经验法则 是不是您要音译的脚本来自拉丁语越远 字母,音译会越差。
请注意,这个模块通常比简单地产生更好的结果 从字符中去除重音符号(可以在 Python 中使用 内置函数)。它基于手动调整的字符映射, 例如还包含符号的 ASCII 近似值和 非拉丁字母。
【讨论】:
这对于去除重音非常有效,但除非我做错了什么,否则它似乎无法解决问题的其他方面。欣赏 Unidecode 的介绍。一个有趣的阅读,虽然它不会在我的情况下工作。 它也可以工作 def remove_accents(data): return unicodedata.normalize('NFKD', data).encode('ASCII', 'ignore') @RanvijaySachan 有什么区别? 我不明白为什么if unicodedata.category(c) != 'Mn'
条件会将输出从重音字符更改为非重音字符?
我认为这并不完全正确。它确实规范了口音,但它也完全删除了所有非英语字符。如果一个句子包含像θ
这样的希腊字母,它们会被完全删除。【参考方案2】:
你可以使用str.translate:
import collections
import string
table = collections.defaultdict(lambda: None)
table.update(
ord('é'):'e',
ord('ô'):'o',
ord(' '):' ',
ord('\NNO-BREAK SPACE'): ' ',
ord('\NEN SPACE'): ' ',
ord('\NEM SPACE'): ' ',
ord('\NTHREE-PER-EM SPACE'): ' ',
ord('\NFOUR-PER-EM SPACE'): ' ',
ord('\NSIX-PER-EM SPACE'): ' ',
ord('\NFIGURE SPACE'): ' ',
ord('\NPUNCTUATION SPACE'): ' ',
ord('\NTHIN SPACE'): ' ',
ord('\NHAIR SPACE'): ' ',
ord('\NZERO WIDTH SPACE'): ' ',
ord('\NNARROW NO-BREAK SPACE'): ' ',
ord('\NMEDIUM MATHEMATICAL SPACE'): ' ',
ord('\NIDEOGRAPHIC SPACE'): ' ',
ord('\NIDEOGRAPHIC HALF FILL SPACE'): ' ',
ord('\NZERO WIDTH NO-BREAK SPACE'): ' ',
ord('\NTAG SPACE'): ' ',
)
table.update(dict(zip(map(ord,string.ascii_uppercase), string.ascii_lowercase)))
table.update(dict(zip(map(ord,string.ascii_lowercase), string.ascii_lowercase)))
table.update(dict(zip(map(ord,string.digits), string.digits)))
print('123 fôé BAR҉'.translate(table,))
产量
123 foe bar
不利的一面是,您必须列出所有要翻译的特殊重音字符。 @gnibbler 的方法需要更少的编码。
从好的方面来说,str.translate
方法应该相当快,并且一旦设置了table
,它就可以在一个函数调用中处理您的所有要求(小写、删除和删除重音符号)。
顺便说一句,200K 字符的文件不是很大。因此,将整个文件读入单个str
,然后在一个函数调用中翻译它会更有效。
【讨论】:
性能似乎与我的方法相同(两种情况下都是 0.96875 秒),但这不那么骇人听闻。谢谢。关于一次翻译整个文件,我需要保留文本格式,因为我正在使用诸如 csv 之类的数据文件。以上是关于Python:替换重音符号(é 到 e)、删除 [^a-zA-Z\d\s] 和 lower() 的有效方法 [重复]的主要内容,如果未能解决你的问题,请参考以下文章