【问题标题】:Return a set of pairs of keys from a dictionary that have a common value从字典中返回一组具有共同值的键对
【发布时间】:2019-04-24 12:48:51
【问题描述】:

我如何编写一个函数,它需要一个字典并返回一个集合,该集合由具有至少一个共同值的键对组成?

例子:

我有以下字典:

dict = {
'C': {'123'}, 
'A': {'123', '456'}, 
'D': {'123'}, 
'B': {'789', '456'}, 
'E': {'789'}}

MyFunction(dict) 应该返回我:

{("A", "B"), ("A", "C"), ("A", "D"), ("B", "E"), ("C", "D")}

【问题讨论】:

  • 旁注:从不(即使作为示例)影子内置插件,例如使用ddctdict_ 而不是dict

标签: python python-3.x function dictionary set


【解决方案1】:

使用itertools.combinations

from itertools import combinations

d = {
    'C': {'123'}, 
    'A': {'123', '456'}, 
    'D': {'123'}, 
    'B': {'789', '456'}, 
    'E': {'789'}
}

def MyFunction(d):
    out = set()
    for i, j in combinations(d, 2):
        if d[j].intersection(d[i]) and (i, j) not in out and (j, i) not in out:
            out.add((i, j))
    return set(tuple(sorted(i)) for i in out)

print(MyFunction(d))
print(MyFunction(d) == {("A", "B"), ("A", "C"), ("A", "D"), ("B", "E"), ("C", "D")})

输出是:

{('A', 'D'), ('A', 'B'), ('B', 'E'), ('A', 'C'), ('C', 'D')}
True

如果你认为('A', 'C')('C', 'A')相同,可以替换

return set(tuple(sorted(i)) for i in out)

只有

return out

【讨论】:

    【解决方案2】:

    更有效的一次性解决方案是使用seen dict 来跟踪迄今为止“看到”给定值的键列表:

    pairs = set()
    seen = {}
    for key, values in d.items():
        for value in values:
            if value in seen:
                for seen_key in seen[value]:
                    pairs.add(frozenset((key, seen_key)))
            seen.setdefault(value, []).append(key)
    

    pairs 会变成:

    {frozenset({'D', 'A'}), frozenset({'B', 'E'}), frozenset({'B', 'A'}), frozenset({'C', 'D'}), frozenset({'C', 'A'})}
    

    如果需要,您可以轻松地将其转换为一组按字典顺序排序的元组:

    {tuple(sorted(p)) for p in pairs}
    

    返回:

    {('A', 'C'), ('B', 'E'), ('C', 'D'), ('A', 'D'), ('A', 'B')}
    

    【讨论】:

      【解决方案3】:

      defaultdict + combinations

      对于蛮力解决方案,您可以反转集合字典,然后使用集合推导:

      from collections import defaultdict
      from itertools import combinations
      
      d = {'C': {'123'}, 'A': {'123', '456'}, 
           'D': {'123'}, 'B': {'789', '456'}, 
           'E': {'789'}}
      
      dd = defaultdict(set)
      
      for k, v in d.items():
          for w in v:
              dd[w].add(k)
      
      res = {frozenset(i) for v in dd.values() if len(v) >= 2 for i in combinations(v, 2)}
      
      print(res)
      
      {frozenset({'A', 'D'}), frozenset({'C', 'D'}),
       frozenset({'B', 'E'}), frozenset({'B', 'A'}),
       frozenset({'C', 'A'})}
      

      您可以看到 res 中的项目是 frozenset 对象,即它们不依赖于元组内的排序。需要frozenset 而不是set,因为set 不可散列。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-11-30
        • 1970-01-01
        • 2022-01-18
        相关资源
        最近更新 更多