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() 的有效方法 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

如何从 .NET 中的字符串中删除变音符号(重音符号)?

如何从 .NET 中的字符串中删除变音符号(重音符号)?

可以使 REPLACE() 不区分重音(é = e)吗?

在 Python 中,如何对包含重音符号的数据框进行排序?

Java 删除字符串上的标点符号(也包括“”和所有这些)维护重音字符

删除重音和特殊字符[重复]