Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/304.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 拉丁语-1到ascii_Python_Unicode - Fatal编程技术网

Python 拉丁语-1到ascii

Python 拉丁语-1到ascii,python,unicode,Python,Unicode,我有一个带有重音拉丁字符的unicode字符串,例如 n=unicode('Wikipédia, le projet d’encyclopédie','utf-8') 我想把它转换成普通的ascii码,即“维基百科,le projet DenCypropedie”,所以所有尖锐/重音、cedilla等都应该删除 最快的方法是什么,因为它需要匹配一个长的自动完成下拉列表 结论: 我的标准之一是速度,Lennart的“为unicode编码/解码注册您自己的错误处理程序”给出了最好的结果(参见Ale

我有一个带有重音拉丁字符的unicode字符串,例如

n=unicode('Wikipédia, le projet d’encyclopédie','utf-8')
我想把它转换成普通的ascii码,即“维基百科,le projet DenCypropedie”,所以所有尖锐/重音、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')
所以在第二行中,我们从2-10得到字符,但我们只转换第二个字符,所以如果我们返回error,则返回3作为继续点

¼ éíñ§ÐÌëÑ » ¼ ö ® © ’
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 '
¼ éíñ§ÐÌëÑ » ¼ ö ® © ’
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会更快,但出于演示目的,我将其保持简单


有关更多详细信息,请参见

,我认为Unicode字符串的.translate方法是最快的解决方案。不过,您肯定应该自己进行测量。

(并翻译),然后转换为ascii:

intab = u'áéí'  # extend as needed
outtab = u'aei' # as well as this one
table = maketrans(intab, outtab)

text = translate(u"Wikipédia, le projet d’encyclopédie", table)

try:
    temp = unicode(text, "utf-8")
    fixed = unicodedata.normalize('NFKD', temp).encode('ASCII', action)
    return fixed
except Exception, errorInfo:
    print errorInfo
    print "Unable to convert the Unicode characters to xml character entities"
    raise errorInfo
(from)

这样做的“正确”方法是为unicode编码/解码注册您自己的错误处理程序,并在该错误处理程序中提供从è到e和ö到o的替换,等等

像这样:

# -*- coding: UTF-8 -*-
import codecs

map = {u'é': u'e',
       u'’': u"'",
       # ETC
       }

def asciify(error):
    return map[error.object[error.start]], error.end

codecs.register_error('asciify', asciify)

test = u'Wikipédia, le projet d’encyclopédie'
print test.encode('ascii', 'asciify')

您也可以在IBM的库和Python绑定中找到一些内容,不过,这可能会减少工作量。

因此,这里有三种方法,或多或少与其他答案中给出或建议的方法相同:

# -*- coding: utf-8 -*-
import codecs
import unicodedata

x = u"Wikipédia, le projet d’encyclopédie"

xtd = {ord(u'’'): u"'", ord(u'é'): u'e', }

def asciify(error):
    return xtd[ord(error.object[error.start])], error.end

codecs.register_error('asciify', asciify)

def ae():
  return x.encode('ascii', 'asciify')

def ud():
  return unicodedata.normalize('NFKD', x).encode('ASCII', 'ignore')

def tr():
  return x.translate(xtd)

if __name__ == '__main__':
  print 'or:', x
  print 'ae:', ae()
  print 'ud:', ud()
  print 'tr:', tr()
以main运行时,会发出:

or: Wikipédia, le projet d’encyclopédie
ae: Wikipedia, le projet d'encyclopedie
ud: Wikipedia, le projet dencyclopedie
tr: Wikipedia, le projet d'encyclopedie
清楚地表明,基于unicodedata的方法虽然不需要翻译图
xtd
,但它不能以自动方式正确翻译所有字符(它适用于重音字母,但不适用于反撇号),因此它还需要一些辅助步骤来显式处理这些字符(毫无疑问,在它现在的身体之前)

性能也很有趣。在使用Mac OS X 10.5和system Python 2.5的笔记本电脑上,可以重复使用:

$ python -mtimeit -s'import a' 'a.ae()'
100000 loops, best of 3: 7.5 usec per loop
$ python -mtimeit -s'import a' 'a.ud()'
100000 loops, best of 3: 3.66 usec per loop
$ python -mtimeit -s'import a' 'a.tr()'
10000 loops, best of 3: 21.4 usec per loop
translate
的速度惊人地慢(相对于其他方法)。我认为问题在于,dict是针对
translate
案例中的每个字符进行检查的(大多数都没有),但只针对
asciify
方法中的少数字符

为了完整起见,这里有一种“增强的unicodedata”方法:

specstd = {ord(u'’'): u"'", }
def specials(error):
  return specstd.get(ord(error.object[error.start]), u''), error.end
codecs.register_error('specials', specials)

def bu():
  return unicodedata.normalize('NFKD', x).encode('ASCII', 'specials')
这提供了正确的输出,但是:

$ python -mtimeit -s'import a' 'a.bu()'
100000 loops, best of 3: 10.7 usec per loop
<>……速度并不是那么好。因此,如果速度很重要,毫无疑问,要完成一个完整的<代码> XTD/<代码>翻译DICT,并使用<代码> ASCISIZION/COD>方法。当每次翻译的额外微秒没有什么大不了的时候,人们可能只想考虑<代码> BU/COD>方法,只是为了方便。(只需要翻译口述就可以了,希望只有少数特殊字符不能正确翻译基本的unicodedata思想)。

Aweasome模块可以为您做到这一点:

>>> import unidecode
>>> n = unicode('Wikipédia, le projet d’encyclopédie','utf-8')
>>> unidecode.unidecode(n)
"Wikipedia, le projet d'encyclopedie"
包裹是

Unicode文本的US-ASCII音译。
Python unidecode的改进版本,即Sean M.Burke的Python文本端口::unidecode Perl模块

然后在
python

import unihandecode
print(unihandecode.unidecode(u'Wikipédia, le projet d’encyclopédie'))


打印
Wikipedia,le projet d'Encyclopedia

,但这会将它们转换为xml字符实体。这不是他要求的。我不理解解决方案的第一行“Maketrans(和translate)然后转换为ascii:为什么需要这样做,而你不在代码中的任何地方使用它?@Lennart Regebro:然后它用ASCII编码。@Anurag Uniyal:他想用“e”替换例如“é”,这对他来说是普通转换所不能做到的。这就是为什么需要maketrans。我在这里复制的代码片段只显示unicode->ASCII转换。我添加了maketrans示例。@sztomi:这里的问题是,他希望将非ascii字符转换为ascii字符,而您的示例没有这样做。您的maketrans示例甚至没有使用unicode…+1:我只想对Ascify函数的输入添加一些检查,但我认为这对于unicode enco中的自定义错误处理也是一个非常快速和好的参考丁。我同意这是正确的实现。也许有人可以建议一个通用的完整映射。+1是正确的答案,但我想我会选择Alex的答案,因为它是完整的,并且包括计时。此外,Ascify应该将所有字符从error.start转换为error.end感谢总结和计时:)在创建dict时使用“ord”命令,而在ascifig时又使用“ord”命令,这有什么原因吗?@Anurag,dict这样做的原因是为了让它在
中立即可用。翻译
--
ascifid
当然不需要这样做。简化后,它的时间大约从7.5秒减少到了7.3秒。我肯定你知道,但是注意不要向用户显示这些ascii字符串。当你或多或少随机地改变字母时,单词的意思可能会完全改变(将“ö”变成“o”等等)是的,这不是用于显示,而是用于键入,我们有一个带有ascii字母的屏幕键盘。问题是用户如何键入é或õ,所以如果键入e,它应该匹配带有e,é,ê的字符串。我不明白你对
错误的替换。start+1
表示
错误。end
。你能解释一下吗?这两种方法对我来说都一样。@go我已经添加了疑问的原因,知道替换某些字符可以
import unihandecode
print(unihandecode.unidecode(u'Wikipédia, le projet d’encyclopédie'))