Python Forum
Merge dicts without override
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Merge dicts without override
#1
Just as an FYI I'm still new to working with dicts so the way I have these structured could probably be improved. Basically I have 3 dicts with different information pertaining to individuals contained in each. Each individual has an ID and that is used as the keys. I've tried multiple ways of combining them but each method results in the data being overridden. Also, some ID keys may not be in all of the dicts.

Below are examples of each dict. If anyone has a way of accomplishing this task and/or advice on how to improve the structures I would appreciate it.

#alias dict
{
    "10084": {
        "aliases": {
            "first_last": "Loren Meyer",
            "last_first": "Meyer, Loren"
        }
    },
    "10111": {
        "aliases": {
            "first_last": "Cory Higgins",
            "last_first": "Higgins, Cory"
        }
    },
    "10163": {
        "aliases": {
            "first_last": "Antoine Wright",
            "last_first": "Wright, Antoine"
        }
    }
}

#vitals dict
{
    "10084": {
        "vitals": {
            "ht": 82,
            "wt": 257,
            "birth_date": "12/30/1972"
        }
    },
    "10111": {
        "vitals": {
            "ht": 77,
            "wt": 180,
            "birth_date": "6/14/1989"
        }
    },
    "10163": {
        "vitals": {
            "ht": 79,
            "wt": 210,
            "birth_date": "2/6/1984"
        }
    }
}

#combine dict
{
    "10084": {
        "combine": {
            "span": 81.0,
            "reach": 100.0,
            "body_fat": 4.1,
        }
    },
    "10111": {
        "combine": {
            "span": 81.0,
            "reach": 100.0,
            "body_fat": 9.1,
        }
    },
    "10163": {
        "combine": {
            "span": 75.0,
            "reach": 85.0,
            "body_fat": 6.1,
        }
    }
}
Reply
#2
Loop through the keys (10084, 10111, and 10163). For each key do aliases[key].update(vitals[key]) and aliases[key].update(combine[key]). You can use 'if key in dict' or try/except to handle keys that aren't in vitals or combine.
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#3
ichabod801 algorithm expressed in Python code:

combined = dict()
                                                      
for d in (alias, vitals, combine): 
    for key, value in d.items(): 
        try: 
            combined[key].update(value) 
        except KeyError: 
            combined[key] = dict(value)
If defaultdict is OK then code can be even simpler:

combined = defaultdict(dict)                                               

for d in (alias, vitals, combine): 
    for key, value in d.items(): 
        combined[key].update(value) 
I'm not 'in'-sane. Indeed, I am so far 'out' of sane that you appear a tiny blip on the distant coast of sanity. Bucky Katt, Get Fuzzy

Da Bishop: There's a dead bishop on the landing. I don't know who keeps bringing them in here. ....but society is to blame.
Reply
#4
Generalized version to use as many dicts as you want.
All values of the dicts must be dicts, otherwise this code won't work.

import pprint


d1 = {
    "10084": {
        "aliases": {
            "first_last": "Loren Meyer",
            "last_first": "Meyer, Loren"
        }
    },
    "10111": {
        "aliases": {
            "first_last": "Cory Higgins",
            "last_first": "Higgins, Cory"
        }
    },
    "10163": {
        "aliases": {
            "first_last": "Antoine Wright",
            "last_first": "Wright, Antoine"
        }
    }
}
 
#vitals dict
d2 = {
    "10084": {
        "vitals": {
            "ht": 82,
            "wt": 257,
            "birth_date": "12/30/1972"
        }
    },
    "10111": {
        "vitals": {
            "ht": 77,
            "wt": 180,
            "birth_date": "6/14/1989"
        }
    },
    "10163": {
        "vitals": {
            "ht": 79,
            "wt": 210,
            "birth_date": "2/6/1984"
        }
    }
}
 
#combine dict
d3 = {
    "10084": {
        "combine": {
            "span": 81.0,
            "reach": 100.0,
            "body_fat": 4.1,
        }
    },
    "10111": {
        "combine": {
            "span": 81.0,
            "reach": 100.0,
            "body_fat": 9.1,
        }
    },
    "10163": {
        "combine": {
            "span": 75.0,
            "reach": 85.0,
            "body_fat": 6.1,
        }
    }
}


def combine_subdicts(*dicts):
    if len(dicts) < 2:
        raise ValueError('Minimum two dicts are required to combine')
    result = {}
    for uid, data in dicts[0].items():
        try:
            for subdict in dicts[1:]:
                data.update(subdict[uid])
        except KeyError:
            print(f'Inconsistent. Missing id {uid} in {subdict}')
            continue
        result[uid] = data
    return result


combined_dict = combine_subdicts(d1, d2, d3)
pprint.pprint(combined_dict, indent=2)
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply
#5
@DeaD_EyE - I like this approach but there is 1 issue. It works perfect for the alias/vitals dicts (they have identical ID groups) but some individuals do not have combine data (and I would anticipate adding a few other dicts that may not have all ID's). I tried replacing continue with pass below the KeyError line but that didn't seem to make a difference. Any ideas on how to alter the script to better handle missing ID's?
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  python update binary object (override delivered Object properties) pierre38 4 1,711 May-19-2022, 07:52 AM
Last Post: pierre38
  dict class override: how access parent values? Andrey 1 1,594 Mar-06-2022, 10:49 PM
Last Post: deanhystad
  Due to MDLable ID does not have get attribute how to override on this jayyu 0 2,789 Dec-20-2021, 10:38 AM
Last Post: jayyu
  Override a library function that is not in __all__ Weird 7 3,220 Aug-23-2021, 05:03 PM
Last Post: Larz60+
Star Recursively convert nested dicts to dict subclass Alfalfa 1 2,840 Jan-22-2021, 05:43 AM
Last Post: buran
  Split dict of lists into smaller dicts of lists. pcs3rd 3 2,312 Sep-19-2020, 09:12 AM
Last Post: ibreeden
  Still working with dicts menator01 2 1,974 Nov-07-2019, 07:15 AM
Last Post: perfringo
  convert List of Dicts into a 2 deep Nested Dict rethink 1 3,158 Aug-23-2019, 05:28 PM
Last Post: ichabod801
  Could I override a fully implemented method zatlas1 2 2,382 Jun-06-2019, 02:20 AM
Last Post: zatlas1
  How can we override decorator? bhojendra 2 9,256 May-12-2019, 11:15 PM
Last Post: ichabod801

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020