产品-国家映射的逆向逻辑

Reversing logic of a product-country mapping

我有一本字典,可以将 territory_code 映射到 productIds 可用的内容:

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

我想反转映射,以便它为我提供项目并将其映射到领土。它应该给我:

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

我该怎么做这个倒车?

你可以试试暴力破解的方式。

逻辑 - 为旧字典中的每个值在新字典中创建一个新键并将旧键添加为新值

>>> 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'])}

没有 REPL 箭头的裸代码

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

这里有个小提示。如果允许导入,则可以使用 collections

中的 defaultdict
>>> 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'])}

这样就可以避免在中间使用if子句。

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

使用多行方法更具可读性,但这里有一个单行方法只是为了好玩:

>>> 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'])}