从特殊字符列表创建字典
我正在做一个小脚本:基本上是把列表中的元素(里面有特殊字符)映射到它们的索引,创建一个字典。
#!/usr/bin/env python
#-*- coding: latin-1 -*-
ln1 = '?0>9<8~7|65"4:3}2{1+_)'
ln2 = "(*&^%$£@!/`'\][=-#¢"
refStr = ln2+ln1
keyDict = {}
for i in range(0,len(refStr)):
keyDict[refStr[i]] = i
print "-" * 32
print "Originl: ",refStr
print "KeyDict: ", keyDict
# added just to test a few special characters
tsChr = ['£','%','\\','¢']
for k in tsChr:
if k in keyDict:
print k, "\t", keyDict[k]
else: print k, "\t", "not in the dic."
它返回的结果是这样的:
Originl: (*&^%$£@!/`'\][=-#¢?0>9<8~7|65"4:3}2{1+_)
KeyDict: {'!': 9, '\xa3': 7, '\xa2': 20, '%': 4, '$': 5, "'": 12, '&': 2, ')': 42, '(': 0, '+': 40, '*': 1, '-': 17, '/': 10, '1': 39, '0': 22, '3': 35, '2': 37, '5': 31, '4': 33, '7': 28, '6': 30, '9': 24, '8': 26, ':': 34, '=': 16, '<': 25, '?': 21, '>': 23, '@': 8, '\xc2': 19, '#': 18, '"': 32, '[': 15, ']': 14, '\\': 13, '_': 41, '^': 3, '`': 11, '{': 38, '}': 36, '|': 29, '~': 27}
这都没问题,除了字符 £
、%
和 \
被转换成了 \xa3
、\xa2
和 \\
。有人知道为什么打印 ln1
/ln2
没问题,但字典却不行吗?我该怎么解决这个问题呢?非常感谢任何帮助。谢谢!!
更新 1
我添加了一些额外的特殊字符 - #
和 ¢
,然后根据 @Duncan 的建议,我得到了这个结果:
! 9
? 7
? 20
% 4
$ 5
....
....
8 26
: 34
= 16
< 25
? 21
> 23
@ 8
? 19
....
....
注意第7、第19和第20个元素,完全没有正确打印。第21个元素是实际的 ?
字符。谢谢!!
更新 2
我刚刚在我的原始帖子中添加了这个循环,实际上是为了测试我的目的:
tsChr = ['£','%','\\','¢']
for k in tsChr:
if k in keyDict:
print k, "\t", keyDict[k]
else: print k, "\t", "not in the dic."
这是我得到的结果:
£ not in the dic.
% 4
\ 13
¢ not in the dic.
在运行脚本时,它认为 £
和 ¢
实际上不在字典里 - 这就是我的问题。有人知道怎么解决这个,或者我哪里做错了吗?
最终,我会检查文件(或一行文本)中的字符是否在字典里,以查看它是否存在,并且文本中可能会有像 é
或 £
这样的字符。谢谢!!
2 个回答
当你打印一个包含字符串的字典或列表时,Python会显示这些字符串的repr()
形式。如果你执行print repr(ln2)
,你会发现没有任何变化:你的字典键只是'£'等字符的latin-1编码。
如果你这样做:
for k in keyDict:
print k, keyDict[k]
那么字符就会按照你预期的方式显示出来。
在我看来,了解一下unicode的基本知识以及它在Python中的应用是很有用的。
如果你不想知道为什么人们搞得这么复杂,以至于你需要处理'\xa3'而不是直接用一个简单的£
,那么Duncan上面的回答就非常完美,能告诉你你想知道的一切。
更新(关于你的更新 #2)
请确认你的文件是用latin-1编码保存的,而不是utf-8,这样你的测试就会通过(或者直接把#-*- coding: latin-1 -*-
改成#-*- coding: utf-8 -*-
)。
这个问题你可以通过阅读我上面链接的内容轻松理解:
你的文件是以utf-8格式保存的,这意味着字符£
使用了2个字节,但因为你告诉Python解释器编码是latin-1,所以它会把£
的每个字节当作一个键来使用。
实际上,我可以在ln2
中数出19个字符,但如果你执行len(ln2)
,它会返回21。
当你测试'£' in keyDict.keys()
时,你在寻找一个2个字符的字符串,而字典中每个字符都有自己的键,这就是为什么找不到它的原因。
你也可以测试len(keyDict)
,会发现它比你预期的要长。
我想这解释了一切,请理解并不是所有的内容都能在一个网页上简单明了地解释,但我认为上面的链接是一个不错的起点,里面有一些故事和代码示例。
祝好
附言:我用这个代码,保存为UTF-8格式,运行得非常顺利:
#!/usr/bin/env python
#-*- coding: utf-8 -*-
ln1 = u'?0>9<8~7|65"4:3}2{1+_)'
ln2 = u"(*&^%$£@!/`'\][=-#¢"
refStr = u"%s%s" % (ln2, ln1)
keyDict = {}
for idx, chr_ in enumerate(refStr):
print chr_,
keyDict[chr_] = idx
print u"-" * 32
print u"Originl: ", refStr
print u"KeyDict: ", keyDict
tsChr = [u'£', u'%', u'\\', u'¢']
for k in tsChr:
if k in keyDict.keys():
print k, "\t", keyDict[k]
else: print k, repr(k), "\t", "not in the dic."