Return a set of pairs of keys from a dictionary that have a common value
up vote
2
down vote
favorite
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:
{("A", "B"), ("A", "C"), ("A", "D"), ("B", "E"), ("C", "D")}
python python-3.x function dictionary set
add a comment |
up vote
2
down vote
favorite
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:
{("A", "B"), ("A", "C"), ("A", "D"), ("B", "E"), ("C", "D")}
python python-3.x function dictionary set
Side note: never (even as an example) shadow built-ins, e.g. used
ordct
ordict_
instead ofdict
.
– jpp
Nov 21 at 21:49
add a comment |
up vote
2
down vote
favorite
up vote
2
down vote
favorite
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:
{("A", "B"), ("A", "C"), ("A", "D"), ("B", "E"), ("C", "D")}
python python-3.x function dictionary set
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:
{("A", "B"), ("A", "C"), ("A", "D"), ("B", "E"), ("C", "D")}
python python-3.x function dictionary set
python python-3.x function dictionary set
edited Nov 21 at 21:40
jpp
86.2k194898
86.2k194898
asked Nov 21 at 21:30
Tadej Firšt
155
155
Side note: never (even as an example) shadow built-ins, e.g. used
ordct
ordict_
instead ofdict
.
– jpp
Nov 21 at 21:49
add a comment |
Side note: never (even as an example) shadow built-ins, e.g. used
ordct
ordict_
instead ofdict
.
– jpp
Nov 21 at 21:49
Side note: never (even as an example) shadow built-ins, e.g. use
d
or dct
or dict_
instead of dict
.– jpp
Nov 21 at 21:49
Side note: never (even as an example) shadow built-ins, e.g. use
d
or dct
or dict_
instead of dict
.– jpp
Nov 21 at 21:49
add a comment |
3 Answers
3
active
oldest
votes
up vote
1
down vote
accepted
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:
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:
{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')}
add a comment |
up vote
2
down vote
Using 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
return set(tuple(sorted(i)) for i in out)
with just
return out
add a comment |
up vote
1
down vote
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, i.e. they aren't depending on sorting within tuples. frozenset
is required instead of set
since set
is not hashable.
add a comment |
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
accepted
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:
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:
{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')}
add a comment |
up vote
1
down vote
accepted
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:
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:
{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')}
add a comment |
up vote
1
down vote
accepted
up vote
1
down vote
accepted
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:
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:
{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')}
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:
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:
{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')}
answered Nov 21 at 22:07
blhsing
27.6k41335
27.6k41335
add a comment |
add a comment |
up vote
2
down vote
Using 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
return set(tuple(sorted(i)) for i in out)
with just
return out
add a comment |
up vote
2
down vote
Using 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
return set(tuple(sorted(i)) for i in out)
with just
return out
add a comment |
up vote
2
down vote
up vote
2
down vote
Using 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
return set(tuple(sorted(i)) for i in out)
with just
return out
Using 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
return set(tuple(sorted(i)) for i in out)
with just
return out
edited Nov 21 at 23:21
answered Nov 21 at 23:10
slavos1
365
365
add a comment |
add a comment |
up vote
1
down vote
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, i.e. they aren't depending on sorting within tuples. frozenset
is required instead of set
since set
is not hashable.
add a comment |
up vote
1
down vote
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, i.e. they aren't depending on sorting within tuples. frozenset
is required instead of set
since set
is not hashable.
add a comment |
up vote
1
down vote
up vote
1
down vote
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, i.e. they aren't depending on sorting within tuples. frozenset
is required instead of set
since set
is not hashable.
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, i.e. they aren't depending on sorting within tuples. frozenset
is required instead of set
since set
is not hashable.
answered Nov 21 at 21:37
jpp
86.2k194898
86.2k194898
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53420730%2freturn-a-set-of-pairs-of-keys-from-a-dictionary-that-have-a-common-value%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Side note: never (even as an example) shadow built-ins, e.g. use
d
ordct
ordict_
instead ofdict
.– jpp
Nov 21 at 21:49