简体   繁体   中英

update second level dict array object using a reference dict in python

I have an array of dicts and within each one if have another array of dicts. my original dict like this

[{'substepheading': 'Heading 1',
  'substepnumber': '1',
  'substepparams': [{'name': 'upload file', 'paramselected': 'no'}]},
 {'substepheading': 'Heading 2',
  'substepnumber': '2',
  'substepparams': [{'name': 'clean data', 'paramselected': 'no'}]}]

I have another dict which contains the updates to specified step numbers and params like this

[{'substepnumber': 2, 'substepparams': [{'name': 'clean room'}]}]

I tried this but the subarray is not getting updated properly

    for substep in substepdetails:
        for modifiedsubstep in substepdetailstoupdate:
            if((modifiedsubstep['substepnumber']) == int(substep['substepnumber'])):
                substep.update(modifiedsubstep)

The second level array of dicts is getting overridden like this

[{'substepheading': 'choose file',
  'substepnumber': '1',
  'substepparams': [{'name': 'upload file', 'paramselected': 'no'}]},
 {'substepheading': 'prepare the data',
  'substepnumber': '2',
  'substepparams': [{'name': 'clean room'}]}]

I know I can add one more internal loop for this particular case but I was wondering if there is a more elegant way to update dicts in situations like this, especially if there can be multiple sub levels like this

EDIT: Desired output is like this

[{'substepheading': 'choose file',
      'substepnumber': '1',
      'substepparams': [{'name': 'upload file', 'paramselected': 'no'}]},
     {'substepheading': 'prepare the data',
      'substepnumber': '2',
      'substepparams': [{'name': 'clean room', 'paramselected': 'no'}]}]

All you really need is two loops over your data and one loop over your updates (no nested loops). The idea is to create a dict or records that maps substepnumber to substepparams . (Note that this assumes no repetition of substepparams . This case can be handled with a bit extra work.)

For each update, you can access the respective substepnumber in amortized O(1) time and update each dict in the associated substepparams list.

Because records and data reference the same dicts, your original data will be automatically updated.

data = [
    {
        "substepheading": "Heading 1",
        "substepnumber": "1",
        "substepparams": [{"name": "upload file", "paramselected": "no"}],
    },
    {
        "substepheading": "Heading 2",
        "substepnumber": "2",
        "substepparams": [{"name": "clean data", "paramselected": "no"}],
    },
]

# converted substepnumber to str in order to match the data format.
updates = [{"substepnumber": "2", "substepparams": [{"name": "clean room"}]}]

records = {d["substepnumber"]: d["substepparams"] for d in data}
for num, params in ((d["substepnumber"], d["substepparams"]) for d in updates):
    [dct.update(upd) for dct in records[num] for upd in params]


[
    {
        "substepheading": "Heading 1",
        "substepnumber": "1",
        "substepparams": [{"name": "upload file", "paramselected": "no"}],
    },
    {
        "substepheading": "Heading 2",
        "substepnumber": "2",
        "substepparams": [{"name": "clean room", "paramselected": "no"}],
    },
]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM