NeptuneGamer
NeptuneGamer

Reputation: 123

Reversing default dict

I have a defaultdict(list) where my keys are of type tuple and my values are a list of tuples. I want to reverse this dictionary and I have already tried using the zip function and this doesn't work

A sample of my dictionary structure is below

{(2, '-', 3): [('Canada', 'Trudeau'),('Obama', 'USA')]}

Is there anyway to reverse this so I get the keys and values the other way round

Upvotes: 3

Views: 253

Answers (4)

dawg
dawg

Reputation: 103998

Since you have a dict of lists, you need to make the lists an immutable type to use as a key in a Python dict.

You can make the list values tuples:

>>> di={(2, '-', 3): [('Canada', 'Trudeau'),('Obama', 'USA')]}
>>> {tuple(v):k for k, v in di.items()}
{(('Canada', 'Trudeau'), ('Obama', 'USA')): (2, '-', 3)}

Or turn them into strings:

>>> {repr(v):k for k, v in di.items()}
{"[('Canada', 'Trudeau'), ('Obama', 'USA')]": (2, '-', 3)}

With either, you can turn the key back into a list if need be:

>>> from ast import literal_eval
>>> literal_eval("[('Canada', 'Trudeau'), ('Obama', 'USA')]")
[('Canada', 'Trudeau'), ('Obama', 'USA')]

>>> list((('Canada', 'Trudeau'), ('Obama', 'USA')))
[('Canada', 'Trudeau'), ('Obama', 'USA')]

(BTW: Don't use eval if code that might have any outside strings -- use ast.literal_eval in production code as in the example here.)

Lastly, consider this dict:

di={'key 1':'val', 'key 2': 'val', 'key 3': 'val'}

When you reverse the keys and values you will loose data as each key 'val' is added.

You can use a default dict to solve duplicate values becoming keys:

dd=defaultdict(list)
for k, v in di.items():
    dd[v].append(k)

>>> dd
defaultdict(<type 'list'>, {'val': ['key 1', 'key 2', 'key 3']})

Upvotes: 7

David Zemens
David Zemens

Reputation: 53633

Unless I'm misunderstanding what you mean by "reverse" (swapping keys for values, and vice-versa):

You can’t use lists as keys, since lists can be modified in place using index assignments, slice assignments, or methods like append() and extend().

NB: As other answers have suggested, if you cast your lists to some immutable type, you can use those as keys in the dict.

Upvotes: 1

John La Rooy
John La Rooy

Reputation: 304355

If you mean for each tuple from the list to be a key, then this is quite simple (It doesn't matter whether D is a dict or defaultdict here)

>>> D = {(2, '-', 3): [('Canada', 'Trudeau'),('Obama', 'USA')]}
>>> {k1: k for k, v in D.items() for k1 in v}
{('Canada', 'Trudeau'): (2, '-', 3), ('Obama', 'USA'): (2, '-', 3)}

Upvotes: 0

Thomas Baruchel
Thomas Baruchel

Reputation: 7517

You can't do it as it, because your values are mutable: [('Canada', 'Trudeau'),('Obama', 'USA')] is a list and it can't be a key in a dictionary. Maybe you can change that first?

Upvotes: 2

Related Questions