从字符串创建多层字典 [Python]

2 投票
4 回答
2638 浏览
提问于 2025-04-17 12:24

我正在为我的一个网络服务创建一个邮件“机器人”,这个机器人会定期收集要发送的电子邮件队列,然后通过谷歌的SMTP服务器发送这些邮件。我的PHP脚本返回的邮件格式是这样的:

test@example.com:Full Name:shortname\ntest2@example.com:Another Full Name:anothershortname\ntest@example.com:Foo:bar

我需要把它“转换”成像这样的格式:

{
    "test@example.com": [
        [
            "Full Name",
            "shortname"
        ],
        [
            "Foo",
            "bar"
        ]
    ],
    "test2@example.com": [
        [
            "Another Full Name",
            "anothershortname"
        ]
    ]
}

注意,我每封邮件只需要一个键,即使同一个地址出现多次。我知道我可能可以用两个连续的循环来实现,一个循环用来建立字典的第一层,另一个循环用来填充它,但我觉得应该有办法一次性完成。这是我目前的代码:

raw = "test@example.com:Full Name:shortname\ntest2@example.com:Another Full Name:anothershortname\ntest@example.com:Foo:bar"

print raw

newlines = raw.split("\n")

print newlines

merged = {}
for message in newlines:
    message = message.split(":")
    merged[message[0]].append([message[1], message[2]])

print merged

在循环的最后一行,我遇到了一个KeyError错误,我理解为在向某个键添加内容之前,这个键必须先存在(如果尝试向一个不存在的键添加内容,是不会创建这个键的)。

我对Python还很陌生,对列表和字典也不太熟悉,所以非常感谢你的帮助!

4 个回答

1

我看到你已经接受了一个答案,但也许你还是会对你正在做的事情感兴趣,其实可以很简单地用 defaultdict 来实现:

from collections import defaultdict
raw = "test@example.com:Full Name:shortname\ntest2@example.com:Another Full Name:anothershortname\ntest@example.com:Foo:bar"

merged = defaultdict(list)
for line in raw.split('\n'):
    line = line.split(':')
    merged[line[0]].append(line[1:])
1

可能的用法是:

for message in newlines:
    message = message.split(":")
    temp = []
    temp.append(message[1])
    temp.append(message[2])
    merged[message[0]] = temp

实际上可能是:

for message in newlines:
    message = message.split(":")
    temp = []
    temp.append(message[1])
    temp.append(message[2])
    if message[0] not in merged:
        merged[message[0]] = []
    merged[message[0]].append(temp)
0

你说得对,确实有错误。所以你需要检查一下这个键是否存在。'key' in dict 这个表达式会返回 True,如果 'key'dict 里找到了的话;如果没找到,就返回 False。根据这个思路,下面是你的完整代码(去掉了调试用的打印语句):

raw = "test@example.com:Full Name:shortname\ntest2@example.com:Another Full Name:anothershortname\ntest@example.com:Foo:bar"
newlines = raw.split("\n")
merged = {}
for message in newlines:
    message = message.split(":")
    if message[0] in merged:
        merged[message[0]].append([message[1], message[2]])
    else:
        merged[message[0]]=[[message[1], message[2]]]    
print merged

注意倒数第二行的嵌套列表多了个括号。

撰写回答