【发布时间】:2009-09-05 10:44:40
【问题描述】:
我有一个带有重音拉丁字符的 unicode 字符串,例如
n=unicode('Wikipédia, le projet d’encyclopédie','utf-8')
我想将其转换为纯 ascii,即“Wikipedia, le projet dencyclopedie”,因此应删除所有尖锐/口音、cedilla 等
最快的方法是什么,因为它需要匹配一个长的自动完成下拉列表
结论: 由于我的标准之一是速度,Lennart 的“为 unicode 编码/解码注册您自己的错误处理程序”提供了最佳结果(请参阅 Alex 的回答),随着越来越多的字符是拉丁文,速度差异进一步增加。
这是我正在使用的转换表,还修改了错误处理程序,因为它需要处理从 error.start 到 error.end 的整个未编码字符范围
# -*- coding: utf-8 -*-
import codecs
"""
This is more of visual translation also avoiding multiple char translation
e.g. £ may be written as {pound}
"""
latin_dict = {
u"¡": u"!", u"¢": u"c", u"£": u"L", u"¤": u"o", u"¥": u"Y",
u"¦": u"|", u"§": u"S", u"¨": u"`", u"©": u"c", u"ª": u"a",
u"«": u"<<", u"¬": u"-", u"": u"-", u"®": u"R", u"¯": u"-",
u"°": u"o", u"±": u"+-", u"²": u"2", u"³": u"3", u"´": u"'",
u"µ": u"u", u"¶": u"P", u"·": u".", u"¸": u",", u"¹": u"1",
u"º": u"o", u"»": u">>", u"¼": u"1/4", u"½": u"1/2", u"¾": u"3/4",
u"¿": u"?", u"À": u"A", u"Á": u"A", u"Â": u"A", u"Ã": u"A",
u"Ä": u"A", u"Å": u"A", u"Æ": u"Ae", u"Ç": u"C", u"È": u"E",
u"É": u"E", u"Ê": u"E", u"Ë": u"E", u"Ì": u"I", u"Í": u"I",
u"Î": u"I", u"Ï": u"I", u"Ð": u"D", u"Ñ": u"N", u"Ò": u"O",
u"Ó": u"O", u"Ô": u"O", u"Õ": u"O", u"Ö": u"O", u"×": u"*",
u"Ø": u"O", u"Ù": u"U", u"Ú": u"U", u"Û": u"U", u"Ü": u"U",
u"Ý": u"Y", u"Þ": u"p", u"ß": u"b", u"à": u"a", u"á": u"a",
u"â": u"a", u"ã": u"a", u"ä": u"a", u"å": u"a", u"æ": u"ae",
u"ç": u"c", u"è": u"e", u"é": u"e", u"ê": u"e", u"ë": u"e",
u"ì": u"i", u"í": u"i", u"î": u"i", u"ï": u"i", u"ð": u"d",
u"ñ": u"n", u"ò": u"o", u"ó": u"o", u"ô": u"o", u"õ": u"o",
u"ö": u"o", u"÷": u"/", u"ø": u"o", u"ù": u"u", u"ú": u"u",
u"û": u"u", u"ü": u"u", u"ý": u"y", u"þ": u"p", u"ÿ": u"y",
u"’":u"'"}
def latin2ascii(error):
"""
error is protion of text from start to end, we just convert first
hence return error.start+1 instead of error.end
"""
return latin_dict[error.object[error.start]], error.start+1
codecs.register_error('latin2ascii', latin2ascii)
if __name__ == "__main__":
x = u"¼ éíñ§ÐÌëÑ » ¼ ö ® © ’"
print x
print x.encode('ascii', 'latin2ascii')
我为什么返回error.start + 1:
返回的错误对象可以是多个字符,我们只转换其中的第一个,例如如果我将print error.start, error.end 添加到错误处理程序输出是
¼ éíñ§ÐÌëÑ » ¼ ö ® © ’
0 1
2 10
3 10
4 10
5 10
6 10
7 10
8 10
9 10
11 12
13 14
15 16
17 18
19 20
21 22
1/4 einSDIeN >> 1/4 o R c '
所以在第二行我们得到 2-10 的字符,但我们只转换第二个因此返回 3 作为继续点,如果我们返回 error.end 输出是
¼ éíñ§ÐÌëÑ » ¼ ö ® © ’
0 1
2 10
11 12
13 14
15 16
17 18
19 20
21 22
1/4 e >> 1/4 o R c '
我们可以看到 2-10 部分已被单个字符替换。当然,一次性编码整个范围并返回 error.end 会更快,但出于演示目的,我保持简单。
查看http://docs.python.org/library/codecs.html#codecs.register_error了解更多详情
【问题讨论】:
-
我相信您已经知道了,但请注意不要向用户显示这些 ascii-fied 字符串。当您或多或少地随意更改字母时(将“ö”变为“o”等等),单词的含义可能会完全改变。
-
是的,这不是用于显示,而是用于打字,我们有一个带有 ascii 字母的屏幕键盘问题是用户如何键入 é 或 õ,所以如果键入 e,它应该匹配具有 e、é 的字符串, ê 等
-
我不明白你用
error.start+1代替error.end。你能解释一下吗?两者对我来说似乎都一样。 -
@gorus 我已经添加了有问题的原因
-
知道替换某些字符可以get somebody killed