user7123790
user7123790

Reputation:

Grouping strings from a set to a dictionary python

Input:

>>> foo = {("A", "B"), ("A", "G"), ("A", "H"),
...         ("B", "C"), ("B", "H"),
...         ("C", "D"),
...         ("D", "E"), ("D", "G"), ("D", "H"),
...         ("E", "F"), ("E", "G"), ("E", "H"),
...         ("F", "I"), ("F", "J"), ("F", "K"),
...         ("G", "H")}

I am trying to group my set like this, so far I have been unsuccessful, I managed to group them only like this.

Actual output:

>>> {k:set(x[1] for x in v) for k,v in itertools.groupby(sorted(foo), key=lambda x: x[0])}
{'B': {'C', 'H'}, 'E': {'H', 'G', 'F'}, 'D': {'E', 'G', 'H'}, 'A': {'B', 'G', 'H'}, 'C': {'D'}, 'G': {'H'}, 'F': {'I', 'K', 'J'}}

However, this is is my desired output:

foo1  = {"A": {"B", "G", "H"},
         "B": {"A", "H", "C"},
         "C": {"B", "D"},
         "D": {"C", "E", "G", "H"},
         "E": {"D", "F", "G", "H"},
         "F": {"E", "I", "J", "K"},
         "G": {"A", "D", "E", "H"},
         "H": {"A", "B", "D", "E", "G"},
         "I": {"F"},
         "J": {"F"},
         "K": {"F"}
         }

I was thinking with permutations or combinations? But I still don't have an idea how to do it. Thanks in advance. Edit: Added a picture of how the strings are related.

Upvotes: 2

Views: 114

Answers (3)

Patrick Haugh
Patrick Haugh

Reputation: 61052

You can use a regular dictionary, but a defaultdict makes this a little easier.

from collections import defaultdict

d=defaultdict(set)
for key, value in foo:
    f[key].add(value)

With a regular dict:

d = {}
for key, value in foo:
    if key not in d:
        d[key]=set()
    d[key].add(value)

Upvotes: -1

Thomas Grainger
Thomas Grainger

Reputation: 2429

OP requested this to be done with a comprehension, so here's a gratuitous one liner:

(Please, please please don't do it this way)

python3
Python 3.5.2+ (default, Sep 22 2016, 12:18:14) 
[GCC 6.2.0 20160927] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import itertools
>>> import pprint
>>> 
>>> foo = {("A", "B"), ("A", "G"), ("A", "H"),
...         ("B", "C"), ("B", "H"),
...         ("C", "D"),
...         ("D", "E"), ("D", "G"), ("D", "H"),
...         ("E", "F"), ("E", "G"), ("E", "H"),
...         ("F", "I"), ("F", "J"), ("F", "K"),
...         ("G", "H")}
>>> 
>>> foo1 = {k: {x[1] for x in v} for k, v in itertools.groupby(sorted(foo | {(a, b) for b, a in foo}), key=lambda x: x[0])}
>>> pprint.pprint(foo1)
{'A': {'H', 'B', 'G'},
 'B': {'C', 'H', 'A'},
 'C': {'D', 'B'},
 'D': {'C', 'E', 'H', 'G'},
 'E': {'D', 'H', 'F', 'G'},
 'F': {'K', 'J', 'E', 'I'},
 'G': {'D', 'E', 'H', 'A'},
 'H': {'D', 'E', 'B', 'G', 'A'},
 'I': {'F'},
 'J': {'F'},
 'K': {'F'}}

Upvotes: 2

Guillaume
Guillaume

Reputation: 6029

Something like this ?

foo = {("A", "B"), ("A", "G"), ("A", "H"), ("B", "C"), ("B", "H"), ("C", "D"), ("D", "E"), ("D", "G"), ("D", "H"), ("E", "F"), ("E", "G"), ("E", "H"), ("F", "I"), ("F", "J"), ("F", "K"), ("G", "H")}

from collections import defaultdict

result = defaultdict(set)

for key1, key2 in foo:
    result[key1].add(key2)
    result[key2].add(key1)

from pprint import pprint
pprint(result)

Which, contrary to the other answers so far, produces the desired output, albeit unordered:

{'A': {'B', 'G', 'H'},
'B': {'A', 'C', 'H'},
'C': {'B', 'D'},
'D': {'G', 'C', 'H', 'E'},
'E': {'G', 'D', 'H', 'F'},
'F': {'I', 'J', 'K', 'E'},
'G': {'A', 'D', 'H', 'E'},
'H': {'B', 'A', 'G', 'D', 'E'},
'I': {'F'},
'J': {'F'},
'K': {'F'}}

Upvotes: 4

Related Questions