Reputation: 1019
I have two dictionaries, one is a standard key/value pair dictionary and the other is a nested OrderedDict with common key names to the standard dictionary, but has empty values.
I am looking for a way to extract the values from the standard key/value dictionary (properties_dict) and drop these values into my nested dictionary (blank_dict) where the keys match.
I've looked into using 'isinstance' to iterate over values which form other lists/dictionaries, but now I'm beginning to wonder if I am going down the wrong path and possibly overcomplicating it. The other problem I have is one value 'Variant' is in list form, so was looking for a way to pop each value out of the list as it traverses the OrderedDict.
I have added my attempt below.
from collections import OrderedDict
def walkdicts(blankdict, propsdict):
for k, v in blankdict.items():
for k2, v2 in propsdict.items():
if k == k2:
blankdict[k] = v2
if isinstance(v, dict):
walkdicts(v, propsdict)
elif isinstance(v, list):
for i in v:
walkdicts(i[0], propsdict)
return blankdict
properties_dict = {'A_ID': '2702',
'Sys': 'MySystem',
'Namespace': 'SomeNamespace',
'Vers': '112A',
'Variant': ['1','2'],
'SpecID': 'Target1',
'Seq': '12345',
'Match': 'ABCDEFG',
'Time': '200',
'Case1': 'A',
'Type': 'Include',
'MyRef': '1010',
'Case2': 'B'}
blank_dict = OrderedDict([('Main', OrderedDict([
('Vers', ''),
('Namespace', ''),
('Sys', ''),
('A_ID', ''),
('Variant', '1'),
('Sec1', OrderedDict([
('RequestID', OrderedDict([
('Case1', ''),
('Case2', '')])),
('Variant', ''),
('MyRef', '')])),
('Sec2', OrderedDict([
('UHD', OrderedDict([
('SpecID', ''),
('Type', ''),
('AD2W', OrderedDict([
('Time', ''),
('Match', ''),
('Seq', '')]))]))]))]))])
new_dict = walkdicts(blank_dict, properties_dict)
print(new_dict)
Here's the output Ordered dictionary I was looking for:
new_dict = OrderedDict([('Main', OrderedDict([
('Vers', '112A'),
('Namespace', 'SomeNamespace'),
('Sys', 'MySystem'),
('A_ID', '2702'),
('Variant', '1'),
('Sec1', OrderedDict([
('RequestID', OrderedDict([
('Case1', 'A'),
('Case2', 'B')])),
('Variant', '2'),
('MyRef', '1010')])),
('Sec2', OrderedDict([
('UHD', OrderedDict([
('SpecID', 'Target1'),
('Type', 'Include'),
('AD2W', OrderedDict([
('Time', '200'),
('Match', 'ABCDEFG'),
('Seq', '12345')]))]))]))]))])
Thanks for your time.
Upvotes: 2
Views: 116
Reputation: 6902
Here's a function which returns a nested OrderedDict
which matches the structure in template
, with the values populated by performing lookups in props
:
def populate(template, props, prop_indexes=None):
if prop_indexes is None:
prop_indexes = {}
result = OrderedDict()
for k, v in template.items():
if isinstance(v, dict):
result[k] = populate(v, props, prop_indexes)
continue
if k in props.keys():
if isinstance(props[k], list):
if k not in prop_indexes:
prop_indexes[k] = 0
index = prop_indexes[k] % len(props[k])
result[k] = props[k][index]
prop_indexes[k] += 1
else:
result[k] = props[k]
return result
A few notes:
prop_indexes
is used to keep track of where we are for each property that's defined as a list of values. Using the modulus (%
) operator, we can repeatedly cycle through the list if there are more instances in target
than there are values in the listprops
is a dictionary, there's no need to loop through it. Instead, simply check if the key exists.template
consists only of nested dictionaries.Using the definitions of blank_dict
(slightly modified by adding an extra Variant
key, see Note after the output) and properties_dict
from your example code, here's a small bit of code to put it all together:
import pprint
pp = pprint.PrettyPrinter()
print("## blank_dict ##")
pp.pprint(blank_dict)
new_dict = populate_new(blank_dict, properties_dict)
print("## new_dict ##")
pp.pprint(new_dict)
And here's the output (pprint
doesn't really render OrderedDict
all that pretty, but it gets the job done):
## blank_dict ##
OrderedDict([('Main',
OrderedDict([('Vers', ''),
('Namespace', ''),
('Sys', ''),
('A_ID', ''),
('Variant', ''),
('Sec1',
OrderedDict([('RequestID',
OrderedDict([('Case1', ''),
('Case2', '')])),
('Variant', ''),
('MyRef', '')])),
('Sec2',
OrderedDict([('UHD',
OrderedDict([('SpecID', ''),
('Type', ''),
('Variant', ''),
('AD2W',
OrderedDict([('Time',
''),
('Match',
''),
('Seq',
'')]))]))]))]))])
## new_dict ##
OrderedDict([('Main',
OrderedDict([('Vers', '112A'),
('Namespace', 'SomeNamespace'),
('Sys', 'MySystem'),
('A_ID', '2702'),
('Variant', '1'),
('Sec1',
OrderedDict([('RequestID',
OrderedDict([('Case1', 'A'),
('Case2', 'B')])),
('Variant', '2'),
('MyRef', '1010')])),
('Sec2',
OrderedDict([('UHD',
OrderedDict([('SpecID', 'Target1'),
('Type', 'Include'),
('Variant', '1'),
('AD2W',
OrderedDict([('Time',
'200'),
('Match',
'ABCDEFG'),
('Seq',
'12345')]))]))]))]))])
Note: I added an extra Variant
instance to demonstrate populating 3 instances even though there are only 2 values specified in properties_dict
Upvotes: 1