从特殊字符列表创建字典

1 投票
2 回答
15233 浏览
提问于 2025-04-16 21:16

我正在做一个小脚本:基本上是把列表中的元素(里面有特殊字符)映射到它们的索引,创建一个字典。

#!/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 个回答

6

当你打印一个包含字符串的字典或列表时,Python会显示这些字符串的repr()形式。如果你执行print repr(ln2),你会发现没有任何变化:你的字典键只是'£'等字符的latin-1编码。

如果你这样做:

for k in keyDict:
    print k, keyDict[k]

那么字符就会按照你预期的方式显示出来。

3

在我看来,了解一下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."

撰写回答