Reversing logic of a product-country mapping

44 views Asked by At

I have a dictionary that maps the territory_code to what productIds are available:

items = {'US': set(123, 948, 200), 'AG': set(132, 123), 'AZ': set(123)}

I would like to reverse the mapping so it gives me the items and maps those to the territory. It should give me:

{123: set('US', 'AZ', 'AG'), 948: set('US'), 200: set('US'), 132: set('AG')}

How would I do this reversing?

3

There are 3 answers

0
Bhargav Rao On BEST ANSWER

You can try the brute force way.

Logic - For every value in the old dictionary create a new key in the new dictionary and add the old key as the new value

>>> newdic = {}
>>> for k,v in items.items():
...     for i in v:
...         if i not in newdic:
...               newdic[i] = set()
...         newdic[i].add(k)
... 
>>> newdic 
{200: set(['US']), 948: set(['US']), 123: set(['AZ', 'US', 'AG']), 132: set(['AG'])}

Bare code without REPL arrows

for k,v in items.items():
    for i in v:
        if i not in newdic:
              newdic[i] = set()
        newdic[i].add(k)

A small note here. If you are allowed imports then you can use defaultdict from collections

>>> from collections import defaultdict
>>> newdic = defaultdict(set)
>>> for k,v in items.items():
...     for i in v:
...         newdic[i].add(k)
... 
>>> dict(newdic)
{200: set(['US']), 132: set(['AG']), 123: set(['AZ', 'US', 'AG']), 948: set(['US'])}

In this way you can avoid using the if clause in between.

0
tzaman On
rev_map = {}
for code, product_ids in items.items():
    for product_id in product_ids:
        rev_map.setdefault(product_id, set()).add(code)
0
Kevin On

It's more readable to use a multi-line approach, but here's a one-liner just for fun:

>>> items = {'US': {123, 948, 200}, 'AG': {132, 123}, 'AZ': {123}}
>>> {value: {country for country in items if value in items[country]} for value in set.union(*items.values())}
{200: set(['US']), 132: set(['AG']), 123: set(['AZ', 'US', 'AG']), 948: set(['US'])}