我有以下代码:
import string
def translate_non_alphanumerics(to_translate, translate_to='_'):
not_letters_or_digits = u'!"#%\'()*+,-./:;<=>?@[\]^_`{|}~'
translate_table = string.maketrans(not_letters_or_digits,
translate_to
*len(not_letters_or_digits))
return to_translate.translate(translate_table)
适用于非unicode字符串:
>>> translate_non_alphanumerics('<foo>!')
'_foo__'
但unicode字符串失败:
>>> translate_non_alphanumerics(u'<foo>!')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in translate_non_alphanumerics
TypeError: character mapping must return integer, None or unicode
对于str.translate()方法,我无法理解Python 2.6.2 docs中关于“Unicode对象”的段落。
如何使这项工作适用于Unicode字符串?
答案 0 :(得分:56)
Unicode版本的translate需要从Unicode序列(您可以检索具有ord
的单个字符)到Unicode序列的映射。如果要删除字符,请映射到None
。
我改变了你的函数来构建一个dict,将每个字符的序数映射到你想要翻译成的序数:
def translate_non_alphanumerics(to_translate, translate_to=u'_'):
not_letters_or_digits = u'!"#%\'()*+,-./:;<=>?@[\]^_`{|}~'
translate_table = dict((ord(char), translate_to) for char in not_letters_or_digits)
return to_translate.translate(translate_table)
>>> translate_non_alphanumerics(u'<foo>!')
u'_foo__'
编辑:事实证明,转换映射必须从Unicode序号(通过ord
)映射到另一个Unicode序号,Unicode字符串或无(删除)。因此,我将translate_to
的默认值更改为Unicode文字。例如:
>>> translate_non_alphanumerics(u'<foo>!', u'bad')
u'badfoobadbad'
答案 1 :(得分:7)
在这个版本中你可以相对地给别人写一个字母
def trans(to_translate):
tabin = u'привет'
tabout = u'тевирп'
tabin = [ord(char) for char in tabin]
translate_table = dict(zip(tabin, tabout))
return to_translate.translate(translate_table)
答案 2 :(得分:5)
我想出了我的原始函数和Mike版本的以下组合,它与Unicode和ASCII字符串一起使用:
def translate_non_alphanumerics(to_translate, translate_to=u'_'):
not_letters_or_digits = u'!"#%\'()*+,-./:;<=>?@[\]^_`{|}~'
if isinstance(to_translate, unicode):
translate_table = dict((ord(char), unicode(translate_to))
for char in not_letters_or_digits)
else:
assert isinstance(to_translate, str)
translate_table = string.maketrans(not_letters_or_digits,
translate_to
*len(not_letters_or_digits))
return to_translate.translate(translate_table)
更新:“强制”translate_to
为unicode translate_table
进行解码。谢谢迈克。
答案 3 :(得分:4)
对于一个适用于str和unicode对象的简单hack, 在运行translate()之前将转换表转换为unicode:
import string
def translate_non_alphanumerics(to_translate, translate_to='_'):
not_letters_or_digits = u'!"#%\'()*+,-./:;<=>?@[\]^_`{|}~'
translate_table = string.maketrans(not_letters_or_digits,
translate_to
*len(not_letters_or_digits))
translate_table = translate_table.decode("latin-1")
return to_translate.translate(translate_table)
这里的问题是它会隐式地将所有str对象转换为unicode, 如果to_translate包含非ascii字符,则抛出错误。
答案 4 :(得分:0)
不必指定需要替换的所有字符,您也可以反过来查看它,而是只指定有效字符,如下所示:
import re
def replace_non_alphanumerics(source, replacement_character='_'):
result = re.sub("[^_a-zA-Z0-9]", replacement_character, source)
return result
这适用于unicode和常规字符串,并保留类型(如果replacement_character
和source
属于同一类型,显然也是如此。)
答案 5 :(得分:0)
我发现在python 2.7中,类型str
,你会写
import string
table = string.maketrans("123", "abc")
print "135".translate(table)
而对于unicode
类型,您会说
table = {ord(s): unicode(d) for s, d in zip("123", "abc")}
print u"135".translate(table)
在python 3.6中你会写
table = {ord(s): d for s, d in zip("123", "abc")}
print("135".translate(table))
也许这很有帮助。
答案 6 :(得分:0)
与这里的其他人相比,我有一个独特的问题。首先,我知道我的字符串中可能包含Unicode字符。 (感谢在Mac上使用电子邮件...)但是常见的字符之一是Emdash AKA u“ \ u2014”字符,需要将其转换(返回)为两个破折号AKA“-”。可能找到的其他字符是单字符翻译,因此它们与其他解决方案相似。
首先,我为Emdash创建了一个字典。对于这些,我使用一个简单的string.replace()进行转换。其他类似的字符也可以在这里处理。
uTranslateDict = {
u"\u2014": "--", # Emdash
}
然后我为1:1翻译创建了一个元组。这些通过内置的string.translate()进行。
uTranslateTuple = [(u"\u2010", "-"), # Hyphen
(u"\u2013", "-"), # Endash
(u"\u2018", "'"), # Left single quote => single quote
(u"\u2019", "'"), # Right single quote => single quote
(u"\u201a", "'"), # Single Low-9 quote => single quote
(u"\u201b", "'"), # Single High-Reversed-9 quote => single quote
(u"\u201c", '"'), # Left double quote => double quote
(u"\u201d", '"'), # Right double quote => double quote
(u"\u201e", '"'), # Double Low-9 quote => double quote
(u"\u201f", '"'), # Double High-Reversed-9 quote => double quote
(u"\u2022", "*"), # Bullet
]
然后是功能。
def uTranslate(uToTranslate):
uTranslateTable = dict((ord(From), unicode(To)) for From, To in uTranslateTuple)
for c in uTranslateDict.keys():
uIntermediateStr = uToTranslate.decode("utf-8").replace(c, uTranslateDict[c])
return uIntermediateStr.translate(uTranslateTable)
因为我知道输入字符串的格式,所以我不必担心两种类型的输入字符串。