want to do: dict = {'1': ['a'],'2': ['a', 'b', 'c']} invert it to: inv_dict = {'a':['1','2'],'b':['2'],'c':['2']} i know the one liner, if the dict was one to one, inverse = dict((d[k], k) for k in d) can I modify this to work if it was not one to one?

My original attempt: tried to get all of the values from the dict and made it a list then deleted duplicates, using set, then compared original dict keys to check if the certain value existed in that key, if true then change the key in list and append. I can post the code, if needed? Any other suggested way? I feel there has to be a easier way than this.

Comments
good guestion with proper effort

Not simple one liner (of course you can put everything in one line, but it becomes less readable), but I would do:

>>> d
{'1': ['a'], '2': ['a', 'b', 'c']}
>>> values = set(a for b in d.values() for a in b)
>>> values
set(['a', 'c', 'b'])
>>> reverse_d = dict((new_key, [key for key,value in d.items() if new_key in value]) for new_key in values)
>>> reverse_d
{'a': ['1', '2'], 'c': ['2'], 'b': ['2']}
>>>

Edited 5 Years Ago by pyTony: n/a

Comments
usefull and rapid reply

Another way

>>> from operator import itemgetter
>>> from itertools import groupby
>>> dic = {'1': ['a', 'c'],'2': ['a', 'b', 'c'], '3': ['b']}
>>> dict((x, list(t[1] for t in group)) for (x, group) in groupby(sorted(((j, k) for k, v in dic.items() for j in v), key=itemgetter(0)), key=itemgetter(0)))
{'a': ['1', '2'], 'c': ['1', '2'], 'b': ['2', '3']}

Edited 5 Years Ago by Gribouillis: n/a

Comments
This is superfast and exactly what I needed!! Thank you!

Wow, thank you so much. But can you explain how the following line works, as in what each thing does?

>>> reverse_d = dict((new_key, [key for key,value in d.items() if new_key in value]) for new_key in values)

Sorry new to python, it seems much different then pascal or php, which I am used to.

reverse_d = dict( # invoking __init__ method of dict class to create dictionary
             # simple value from the generator in values as key
            (new_key, 
              # value of dictionary by 
              #list comprehension filtering the items by the if condition
              # http://docs.python.org/tutorial/datastructures.html#list-comprehensions
              [key for key,value in d.items() if new_key in value]) 
            # generator for to go through each value in set values (unique)
            for new_key in values)

Edited 5 Years Ago by pyTony: n/a

reverse_d = dict( # invoking __init__ method of dict class to create dictionary
             # simple value from the generator in values as key
            (new_key, 
              # value of dictionary by 
              #list comprehension filtering the items by the if condition
              # http://docs.python.org/tutorial/datastructures.html#list-comprehensions
              [key for key,value in d.items() if new_key in value]) 
            # generator for to go through each value in set values (unique)
            for new_key in values)

wow, so it does what i was attempting to do in 50 lines, in 2 lines. thank you appreciated a lot.

Do not be discouraged even it sounds bit excessive. you get hang of it bit by bit. You had good pseudo-code for whatt to do, that is main thing.

Good thing is that you can write so readable code in Python, only it means that if you use some code you wrote more than week before (or later one month), you are very likely ashamed what you did and fix many things. I did anagram program about two times per week at beginning, sometimes reading my earlier code but not copying to get fluent. The code you can find in code snippet part posted 11.11.11 is version I tried and failed to realize at that time. Main action find_anagrams is only few lines long. I also have around twice faster version, but this simple program program is lot faster than you can read, even in cases when you have tens of thousands of results a it yield them one by one be generator.

Edited 5 Years Ago by pyTony: n/a

This question has already been answered. Start a new discussion instead.