Pythonic Way to reverse nested dictionaries

后端 未结 5 1739
旧巷少年郎
旧巷少年郎 2020-12-14 11:46

I have a nested dictionary of people and item ratings, with people as the key. people may or may not share items. Example:

{
 \'Bob\' : {\'item1\':3, \'item2         


        
相关标签:
5条回答
  • 2020-12-14 12:01

    This is easy enough to do (as others have shown), but depending on your needs you should also consider that for data with several pieces of information where you want to extract by any criterion, a database might be the best tool. The built-in sqlite3 module provides a low-overhead database that may, depending on what you are doing, serve you better than a nested dict.

    0 讨论(0)
  • 2020-12-14 12:14

    I totally agree that Ryan Ginstrom's answer is the preferred way of doing this (for all practical purposes).

    But since the question also explicitely asks:

    Is it possible with a comprehension?

    I thought I'd chime in with a quick example as for how to do this with a list comprehension (it could be a good example for showing how nested list comphrehensions can quickly decrease readability).

    import itertools
    
    d = {
     'Bob' : {'item1':3, 'item2':8, 'item3':6},
     'Jim' : {'item1':6, 'item4':7},
     'Amy' : {'item1':6,'item2':5,'item3':9,'item4':2}
    }
    
    print dict([(x, dict([(k, d[k][x]) for k,v in d.items() if x in d[k]])) 
                for x in set(itertools.chain(*[z for z in d.values()]))])
    
    0 讨论(0)
  • 2020-12-14 12:14

    If you want just access reverse nested dictionaries, Save memory if the dictionary is too large to reverse.

    class mdict2(dict):
        def __init__(self, parent, key1):
            self.parent = parent
            self.key1 = key1
    
        def __getitem__(self, key2):
            return self.parent.mirror[key2][self.key1]
    
    
    class mdict(dict):
        def __init__(self, mirror):
            self.mirror = mirror
    
        def __getitem__(self, key):
            return mdict2(self, key)
    
    d0 = {
     'Bob' : {'item1':3, 'item2':8, 'item3':6},
     'Jim' : {'item1':6, 'item4':7},
     'Amy' : {'item1':6,'item2':5,'item3':9,'item4':2}
    }
    d1 = mdict(d0)
    
    d0['Amy']['item1'] == d1['item1']['Amy']
    # True
    
    0 讨论(0)
  • 2020-12-14 12:15

    Pandas can provide another option. Assume data is the input dictionary.

    import pandas as pd
    output = {i:s.dropna().to_dict() for i, s in pd.DataFrame(data).T.iteritems()}
    
    0 讨论(0)
  • 2020-12-14 12:20

    collections.defaultdict makes this pretty simple:

    from collections import defaultdict
    import pprint
    
    data = {
     'Bob' : {'item1':3, 'item2':8, 'item3':6},
     'Jim' : {'item1':6, 'item4':7},
     'Amy' : {'item1':6,'item2':5,'item3':9,'item4':2}
    }
    
    flipped = defaultdict(dict)
    for key, val in data.items():
        for subkey, subval in val.items():
            flipped[subkey][key] = subval
    
    pprint.pprint(dict(flipped))
    

    Output:

    {'item1': {'Amy': 6, 'Bob': 3, 'Jim': 6},
     'item2': {'Amy': 5, 'Bob': 8},
     'item3': {'Amy': 9, 'Bob': 6},
     'item4': {'Amy': 2, 'Jim': 7}}
    
    0 讨论(0)
提交回复
热议问题