如何展开基于键值 "pairs" 的 python 列表字典?

How to unfold a python dictionary of lists based on key-value "pairs"?

我在使用 Python3.x 列表字典时遇到算法问题,但也许另一种数据结构更合适。

假设我有以下 Python 字典:

dict1 = {1:[4, 12, 22], 2:[4, 5, 13, 23], 3:[7, 15, 25]}

1关联值[4, 12, 22]表示1是"associated with"4。1也关联12,1关联22。另外,2关联与 4 相关联,2 与 5 相关联,2 与 13 相关联,1 与 23 相关联,等等

我的问题是,对于这个小例子,我如何 "unfold" 这个字典使得值列表的每个元素都编码这个 "association"?

即最终结果应该是:

intended_dict = {1:[4, 12, 22], 2:[4, 5, 13, 23], 3:[7, 15, 25], 
                     4:[1, 2], 5:[2], 12:[1], 13:[2], 15:[3], 22:[1], 23:[2], 25:[3]}

因为 4 与 1 关联,4 与 2 关联,5 与 2 关联,等等

有没有这样"unfold"字典的方法?

这将如何扩展到包含包含数百万整数的更大列表的更大字典?

也许另一种数据结构在这里更有效,尤其是对于更大的列表?

编辑:考虑到我正在使用的实际字典的大小(不是上面发布的那个),解决方案应该尽可能 memory-/performance-efficient。

执行以下操作:

intended_dict = dict1.copy()
for k, v in dict1.items():
    for i in v:
        intended_dict.setdefault(i, []).append(k)

一种方法是使用 collections.defaultdict

from collections import defaultdict
dict1 = {1:[4, 12, 22], 2:[4, 5, 13, 23], 3:[7, 15, 25]}
d_dict = defaultdict(list)

for k,l in dict1.items():
    for v in l:
        d_dict[v].append(k)

intended_dict = {**dict1, **d_dict}
print (intended_dict)
#{1: [4, 12, 22], 2: [4, 5, 13, 23], 3: [7, 15, 25], 4: [1, 2], 12: [1], 22: [1], 5: [2], 13: [2], 23: [2], 7: [3], 15: [3], 25: [3]}

简单的一行:

newdict={v:[i for i in dict1.keys() if v in dict1[i]] for k,v in dict1.items() for v in v}
print(newdict)

输出:

{4: [1, 2], 12: [1], 22: [1], 5: [2], 13: [2], 23: [2], 7: [3], 15: [3], 25: [3]}

要合并它们:

print({**dict1,**newdict})

您基本上是在尝试存储关系。关于这个有一个完整的领域——它们存储在关系数据库中,其中包含 。在 Python 中,将其作为 2 列表的列表来执行此操作会更自然——或者,由于您的关系是对称的并且顺序无关紧要,因此是 2 集的列表。不过,更好的解决方案是 pandas,它是在 Python.

中制作表格的规范包

暂时这里是如何将你的原始事物变成一个 pandas 对象,然后将它变成你的固定事物以包含对称性。

import pandas as pd

dict1 = {1:[4, 12, 22], 2:[4, 5, 13, 23], 3:[7, 15, 25]}

relations = pd.DataFrame(
    [[key, value] for key, values in dict1.items() for value in values]
)

print(relations)

Out:
   0   1
0  1   4
1  1  12
2  1  22
3  2   4
4  2   5
5  2  13
6  2  23
7  3   7
8  3  15
9  3  25

result = {
    **{key: list(values) for key, values in relations.groupby(0)[1]},
    **{key: list(values) for key, values in relations.groupby(1)[0]}
}

print(result)

Out:
{1: [4, 12, 22],
 2: [4, 5, 13, 23],
 3: [7, 15, 25],
 4: [1, 2],
 5: [2],
 7: [3],
 12: [1],
 13: [2],
 15: [3],
 22: [1],
 23: [2],
 25: [3]}