对于列表列表,将字典与collections.defaultdict合并

时间:2018-10-08 02:35:54

标签: python python-3.x dictionary defaultdict dictionary-comprehension

这是一个简单的问题,但是我对collections.defaultdict的行为感到困惑。这是为了帮助我了解其工作原理。

这个问题是这个有用问题的推论: How to merge a list of multiple dictionaries into a dictionary of lists?

现在让我们说一下我有一个词典列表列表。我想合并以上问题中详细说明的字典:

list_of_dictionaries2 = [[{0:3523, 1:3524, 2:3540, 4:3541, 5:3542}, 
    {0:7245, 1:7246, 2:7247, 3:7248, 5:7249, 6:7250},
    {1:20898, 2:20899, 3:20900, 4:20901, 5:20902}], [{0:3, 1:4, 2:5, 3:6}]]

预期的答案是这样:

correct2 = [[{0:[3523, 7245], 1:[3524, 7246, 20898], 2:[3540, 7247, 20899], 
            3:[7248, 20900], 4:[3541, 20901], 5:[3542, 7249, 20902], 6:[7250]}], 
            [{0:3, 1:4, 2:5, 3:6}]]

以前,对于单个词典列表,我们通过创建一个空字典以默认值作为列表来解决此问题,即我们使用collections.defaultdict(list)

鉴于这种情况是列表列表,我认为另一个for循环将是解决方案,将字典追加到空列表中:

from collections import defaultdict
correct2 = defaultdict(list)

empty = []

for smaller_list in list_of_dictionaries2:
    for d in smaller_list:
        for k,v in d.items():
            correct2[k].append(v)
    empty.append(correct2)

这是非常错误的。

>>> print(empty)
[defaultdict(<class 'list'>, {0: [3523, 7245, 3], 1: [3524, 7246, 20898, 4], 
2: [3540, 7247, 20899, 5], 4: [3541, 20901], 5: [3542, 7249, 20902], 
3: [7248, 20900, 6], 6: [7250]}), defaultdict(<class 'list'>, 
{0: [3523, 7245, 3], 1: [3524, 7246, 20898, 4], 2: [3540, 7247, 20899, 5], 
4: [3541, 20901], 5: [3542, 7249, 20902], 3: [7248, 20900, 6], 6: [7250]})]

似乎所有词典都被合并了。并且有两个副本。这不是我想要的。

如何针对每个单独的列表执行此操作,如上所示?我的理解在哪里错了?

2 个答案:

答案 0 :(得分:2)

您实际上没有字典列表,但有一个字典列表列表,并且您试图将子列表中的字典合并,因此您应该在循环内初始化defaultdict遍历主列表:

empty = []
for smaller_list in list_of_dictionaries2:
    correct2 = defaultdict(list)
    for d in smaller_list:
        for k,v in d.items():
            correct2[k].append(v)
    empty.append(correct2)

empty将变为:

[defaultdict(<class 'list'>, {0: [3523, 7245], 1: [3524, 7246, 20898], 2: [3540, 7247, 20899], 4: [3541, 20901], 5: [3542, 7249, 20902], 3: [7248, 20900], 6: [7250]}), defaultdict(<class 'list'>, {0: [3], 1: [4], 2: [5], 3: [6]})]

请注意,第二个合并的defaultdict的预期输出不正确,因为每个键的值应为合并后的列表。此外,词典列表列表应在合并后成为列表defaultdict的列表,而不是列表defaultdict的列表。

答案 1 :(得分:1)

您应该像这样在每个循环中初始化$dtUtc = [datetime]::SpecifyKind(($property.value -replace ' UTC$'), 'Utc') $DR.Item($property.Name) = $dtUtc.ToLocalTime() -f "MM/d/yyyy HH:mm:ss"

this.

输出将是

correct2

请注意,defaultdict是可变对象