Skip to content Skip to sidebar Skip to footer

Transpose Values And Key In Python Dictionary When Values Are Not Unique

I want to change keys to values in a python dictionary, but the values in the original dictionary are not unique. Here is what I have: year_person = {2000: ‘Linda’, 2001: ‘Ro

Solution 1:

You can also do it with a defaultdict:

year_person= {2000:'Linda', 2001:'Ron', 2002:'Bruce', 2003:'Linda', 2004:'Bruce', 2005:'Gary', 2006:'Linda'}

fromcollectionsimportdefaultdictd=defaultdict(list)fork,vinyear_person.items():d[v].append(k)printdict(d)>>> {'Bruce': [2002, 2004], 'Linda': [2000, 2003, 2006], 'Ron': [2001], 'Gary': [2005]}

Solution 2:

Just to present some other options and information that may be missing from the current answers:

If you are sure your values are unique, and therefore can become keys, the simplest method is a dict comprehension:

year_person = {2000: 'Linda', 2001: 'Ron', 2002: 'Bruce', 2003: 'Linda', 2004: 'Bruce', 2005: 'Gary', 2006: 'Linda'}
person_year = {key: value for (value, key) in year_person.items()}

Of course, in your case, they are not, so this doesn't work (as it only gives the last value found):

person_year= {'Bruce':2004, 'Linda':2006, 'Ron':2001, 'Gary':2005}

Instead, we can use a nested list comp inside a dict comp:

{key: [value for value, check_key in year_person.items() if check_key==key] for key in year_person.values()}

Giving us:

{'Bruce': [2002, 2004], 'Linda': [2000, 2003, 2006], 'Ron': [2001], 'Gary': [2005]}

This works, but isn't efficient due to having to loop over the entire dictionary for every entry. A much better solution is the defaultdict solution given by alan, which requires only a single loop.

Solution 3:

What you wan't to achieve is technically not feasible. Key to a dictionary cannot be duplicate because if so you cannot uniquely index a dictionary with a key.

What you can do, is to create a dictionary of (key,value) pair where value is the list of all items which has the same key. To achieve it you can do something as follows

>>> person_year={}
>>> [person_year.setdefault(v,[]).append(k) for (k,v) in year_person.iteritems()]
[None, None, None, None, None, None, None]
>>> person_year
{'Bruce': [2002, 2004], 'Linda': [2000, 2003, 2006], 'Ron': [2001], 'Gary': [2005]}
>>> 

Note, if you are only interested in the key value pair and not a dictionary per se' you can just store as a list of tuples as follows

>>> [(v,k) for k,v in year_person.iteritems()][('Linda', 2000), ('Ron', 2001), ('Bruce', 2002), ('Linda', 2003), ('Bruce', 2004), ('Gary', 2005), ('Linda', 2006)]
>>>

Solution 4:

IMO, defaultdict is unnecessary here and doing it as a list comprehension sacrifices readability (though that's not generally the case). Unless profiling indicates that this is really a bottleneck, I would do it as follows:

def invert_to_lists(dct):
    inverted_dict = {}
    for key in dct:
        inverted_dict.setdefault(dct[key], []).append(key)
    return inverted_dict

defaultdict is one more complication. Using setdefault is fine in this case because it only needs to be typed out once. After going through the rigmarole of importing and instantiating a defaultdict, you will have typed more than making the one call to setdefault.

Post a Comment for "Transpose Values And Key In Python Dictionary When Values Are Not Unique"