Python中如何动态创建嵌套字典

9

尝试理解如何动态创建嵌套字典。理想情况下,我的字典应该类似于:

mydict = { 'Message 114861156': { 'email': ['user1@domain.com', 'user2@domain.com'] }, { 'status': 'Queued mail for delivery' }} 

这是我目前的进展:

这里是我目前的进展:

sampledata = "Message 114861156 to user1@domain.com user2@domain.com  [InternalId=260927844] Queued mail for delivery'."

makedict(sampledata)

def makedict(results):
  newdict = {}
  for item in results:
    msgid = re.search(r'Message \d+', item)
    msgid = msgid.group()
    newdict[msgid]['emails'] = re.findall(r'\w+@\w+\.\w+', item)
    newdict[msgid]['status'] = re.findall(r'Queued mail for delivery', item)

输出如下:

Traceback (most recent call last):
  File "wildfires.py", line 57, in <module>
    striptheshit(q_result)
  File "wildfires.py", line 47, in striptheshit
    newdict[msgid]['emails'] = re.findall(r'\w+@\w+\.\w+', item)
KeyError: 'Message 114861156'

你如何动态生成一个类似这样的嵌套字典?

1
请注意,合法的电子邮件地址可以匹配比 r'\w+@\w+\.\w+' 更多的模式。如果您不在受限制的环境中(所有电子邮件地址都在某个公司域中),那么该正则表达式就无效了。您可以在此处阅读更多信息(其中包括一个“基本足够”的正则表达式和一个符合RFC标准的疯狂正则表达式)。 - ShadowRanger
3个回答

11

dict.setdefault()是一个好工具,collections.defaultdict也是如此。

你现在的问题是newdict是一个空字典,因此newdict[msgid]引用了一个不存在的键。这在赋值时可以工作(newdict[msgid] = "foo"),但是由于newdict[msgid]最初未被设置为任何值,所以当您尝试索引它时会得到一个KeyError

dict.setdefault()让您通过最初说“如果msgid存在于newdict中,则给我它的值。 如果没有,则将其值设置为{}并给我那个值”来避开这个问题。

def makedict(results):
    newdict = {}
    for item in results:
        msgid = re.search(r'Message \d+', item).group()
        newdict.setdefault(msgid, {})['emails'] = ...
        newdict[msgid]['status'] = ...
        # Now you KNOW that newdict[msgid] is there, 'cuz you just created it if not!

使用 collections.defaultdict 可以省去调用 dict.setdefault 的步骤。一个 defaultdict 是用一个函数初始化的,该函数生成一个容器,任何不存在的键会被分配为一个值,例如:

from collections import defaultdict

foo = defaultdict(list)
# foo is now a dictionary object whose every new key is `list()`
foo["bar"].append(1)  # foo["bar"] becomes a list when it's called, so we can append immediately
你可以使用这个来表达 "嘿,如果我和你谈论一个新的msgid,我希望它是一个新字典"。
from collections import defaultdict

def makedict(results):
    newdict = defaultdict(dict)
    for item in results:
        msgid = re.search(r'Message \d+', item).group()
        newdict[msgid]['emails'] = ...
        newdict[msgid]['status'] = ...

2

-1

在存储项目之前,您需要创建一个空字典newdict[msgid]

newdict[msgid] = {}

1
除非 newdict[msgid] 已经存在,否则您会清空数据。 - Adam Smith
1
在将物品存储在其中之前 - John Gordon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接