kiprin629
kiprin629

Reputation: 23

flip keys and values in dictionary python

I have a dictionary called z that looks like this


{0: [0.28209479177387814, 0.19947114020071635, 0.10377687435514868, 0.07338133158686996], -1: [0.28209479177387814, 0.19947114020071635, 0.10377687435514868, 0.07338133158686996]}.

I want to flip the values and keys to have

{0.28209479177387814:0, 0.19947114020071635:0, 0.10377687435514868:0, 0.07338133158686996:0, 0.28209479177387814:-1, 0.19947114020071635:-1, 0.10377687435514868:-1, 0.07338133158686996:-1}

The piece of code that seems to work is :

for a in z:
     newdict=dict.fromkeys(z[a],a)

but it only works for one of the keys in z and returns this:

{0.28209479177387814: -1, 0.07338133158686996: -1, 0.10377687435514868: -1, 0.19947114020071635: -1}

what am I doing wrong?

Upvotes: 1

Views: 1513

Answers (3)

radtek
radtek

Reputation: 36300

Easiest way to flip key value in a dict is using dict comprehension, which looks like this: {value: key for key, value in ORIGINAL_DICT.items()}. Full example:

REGION_PREFIX = {
    'AB': 'Alberta',
    'BC': 'British Columbia',
    'IN': 'International',
    'MB': 'Manitoba',
    'NB': 'New Brunswick',
    'NL': 'Newfoundland',
    'NS': 'Nova Scotia',
    'NU': 'Nunavut',
    'NW': 'Northwest Territories',
    'ON': 'Ontario',
    'PE': 'Prince Edward Island',
    'QC': 'Quebec',
    'SK': 'Saskatchewan',
    'US': 'United States',
    'YK': 'Yukon',
}

REGION_PREFIX2 = {value: key for key, value in REGION_PREFIX.items()}

And your output is this:

{'Alberta': 'AB', 'British Columbia': 'BC', 'International': 'IN', 'Manitoba': 'MB', 'New Brunswick': 'NB', 'Newfoundland': 'NL', 'Nova Scotia': 'NS', 'Nunavut': 'NU', 'Northwest Territories': 'NW', 'Ontario': 'ON', 'Prince Edward Island': 'PE', 'Quebec': 'QC', 'Saskatchewan': 'SK', 'United States': 'US', 'Yukon': 'YK'}

Cheers!

Upvotes: 1

bcdan
bcdan

Reputation: 1428

As you have already seen in the comments on your question, Python dictionaries cannot have duplicate keys, since there would be uncertainty as to a correct single value given a key

This could be fixed by having parallel structure to the first, so instead of {value:key}, it would be {value:[key1, key2]}. The code to generate it would be:

new = {}
for key, value in z.items():
  if not value in new:
    new[value] = []
  new[value].append(key)

See Adam Smith's answer for more details.

Upvotes: 4

Adam Smith
Adam Smith

Reputation: 54213

You can't have duplicate keys in a dictionary, but you can pair them together using tuples in a meaningful way.

from itertools import product, chain

tuples = chain.from_iterable(product(vs, [k]) for k, vs in orig_dict.items())
# note this is identical to:
# # tuples = []
# # for k, vs in orig_dict.items():
# #     for tup in [(v, k) for v in vs]:
# #         tuples.append(tup)

That will produce:

[(0.28209479177387814, 0), (0.19947114020071635, 0),
 (0.10377687435514868, 0), (0.07338133158686996, 0),
 (0.28209479177387814, -1), (0.19947114020071635, -1),
 (0.10377687435514868, -1), (0.07338133158686996, -1)]

Now if you really wanted something interesting, you could sort that and group it together.

from itertools import groupby

groups = groupby(sorted(tuples), key=lambda kv: kv[0])

That creates something like:

[(0.07338133158686996, [(0.07338133158686996, 0,
                         0.07338133158686996, -1] ),
 ... ]

You could toss those into a dict by doing:

final_dict = {k: [v[1] for v in vs] for k, vs in groups}

Which should finally give:

{0.07338133158686996: [0, -1],
 ... }

Upvotes: 3

Related Questions