【问题标题】:Merge lists in a dictionary that have a common element合并字典中具有共同元素的列表
【发布时间】:2017-10-17 01:23:44
【问题描述】:

如果值(列表)至少共享一个元素,我想合并字典的键和值。

输入将是:

dico = {"a" : [1,2,3], "b":[9,2,89], "c":[3,12,530],"d":[34,42],"e":[34,6]}

我希望输出是这样的:

{"a,b,c" : [1,2,3,9,89,12,530], "d,e": [34,42,6] }

我尝试过的都没有奏效...你认为这可能吗?

【问题讨论】:

  • 你应该发布你尝试过的内容。
  • 你应该试试union find/disjoint set算法。
  • 应该从加入的列表中删除重复项吗?加入列表中的顺序重要吗?
  • 你在哪个基础上组合了 {"a,b,c" : [1,2,3,9,89,12,530], "d,e": [34,42,6] }?????? >> 而不是 {"a,b,c,d,e" : [1,2,3,9,89,12,530,34,42,6] }!!
  • @DexJ:他说share at least one element。所以ab 共享数字2ac 共享数字3d 仅与e 共享34

标签: python list python-3.x dictionary merge


【解决方案1】:

您可以使用Union-Find aka Disjoin Set 方法。首先,您需要两个函数:unionfind。我通常把它们放在某个地方以备不时之需。

def find(x):
    l = leaders[x]
    if l is not None:
        l = find(l)
        leaders[x] = l
        return l
    return x

def union(x, y):
    lx, ly = find(x), find(y)
    if lx != ly:
        leaders[lx] = ly

现在,您可以使用它们为列表中的每个元素确定一个“领导者”...

dico = {"a" : [1,2,3], "b":[9,2,89], "c":[3,12,530],"d":[34,42],"e":[34,6]}
leaders = collections.defaultdict(lambda: None)

for val in dico.values():
    for other in val[1:]:
        union(val[0], other)        

...然后将具有相同“领导者”的元素分组。

groups = collections.defaultdict(set)
for x in leaders:
    groups[find(x)].add(x)

现在,还按其第一个元素的领导者对键进行分组:

keys = collections.defaultdict(list)
for key in dico:
    keys[find(dico[key][0])].append(key)

最后组装结果。

result = {','.join(ks): groups[leader] for (leader, ks) in keys.items()}
# {'d,e': {42, 34, 6}, 'c,a,b': {1, 2, 3, 9, 12, 530, 89}}

请注意,这是使用集合而不是列表。如果您需要保留原始顺序,只需将键分组,然后将它们各自的列表放在一起。

【讨论】:

  • 非常感谢!! @tobias_k
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-18
  • 2018-10-30
  • 2022-07-26
  • 2018-04-29
相关资源
最近更新 更多