[英]Return a set of pairs of keys from a dictionary that have a common value
How can I write a function, that would take a dictionary and return me a set that would consist of pairs of keys that have at least one common value? 我该如何编写一个函数,该函数需要一个字典并返回一个包含至少有一个公共值的键对的集合?
Example: 例:
I have the following dictionary: 我有以下字典:
dict = {
'C': {'123'},
'A': {'123', '456'},
'D': {'123'},
'B': {'789', '456'},
'E': {'789'}}
MyFunction(dict) should return me: MyFunction(dict)应该返回我:
{("A", "B"), ("A", "C"), ("A", "D"), ("B", "E"), ("C", "D")}
Using itertools.combinations : 使用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")})
Output is: 输出为:
{('A', 'D'), ('A', 'B'), ('B', 'E'), ('A', 'C'), ('C', 'D')}
True
If you consider ('A', 'C')
and ('C', 'A')
same, you can replace 如果您认为
('A', 'C')
和('C', 'A')
相同,则可以替换
return set(tuple(sorted(i)) for i in out)
with just 只是
return out
defaultdict
+ combinations
defaultdict
+ combinations
For a brute force solution, you can invert your dictionary of sets, then use a set comprehension: 对于蛮力解决方案,您可以反转集合字典,然后使用集合理解:
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'})}
As you can see the items in res
are frozenset
objects, ie they aren't depending on sorting within tuples. 如您所见,
res
中的项目是frozenset
对象,即它们不依赖于元组中的排序。 frozenset
is required instead of set
since set
is not hashable. 因为
set
是不可散列的,所以需要frozenset
而不是set
。
A more efficient one-pass solution would be to use a seen
dict that keeps track of a list of keys that have "seen" a given value so far: 一种更有效的单遍解决方案是使用
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
would become: pairs
将变为:
{frozenset({'D', 'A'}), frozenset({'B', 'E'}), frozenset({'B', 'A'}), frozenset({'C', 'D'}), frozenset({'C', 'A'})}
You can then easily transform it to a set of lexicographically sorted tuples if you want: 然后,您可以根据需要轻松地将其转换为一组按字典顺序排序的元组:
{tuple(sorted(p)) for p in pairs}
which returns: 返回:
{('A', 'C'), ('B', 'E'), ('C', 'D'), ('A', 'D'), ('A', 'B')}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.