Home > Enterprise >  update list of dictionaries with values from another list of dictionaries
update list of dictionaries with values from another list of dictionaries

Time:04-29

Given two list of dictionaries:

students = [
    {"id": 1, "name": "A"},
    {"id": 2, "name": "B"},
    {"id": 99, "name": "C"},
    {"id": 4, "name": "D"},
    {"id": 101, "name": "E"},
]

classes = [
    {"id": 1, "students": [1, 99]},
    {"id": 2, "students": [1, 99, 101, 4]},
    {"id": 3, "students": [4, 101]},
]

The classes list has dictionaries with a students key, the values of this key is also a list for example [1, 99] for the first dict {"id": 1, "students": [1, 99]} of classes. I would like to replace these numbers [1,99] with the dictionary from students whenever the id key in students match with the integer present in the key students.

For example, the first result would be : {"id": 1, "students": [{"id": 1, "name": "A"}, {"id": 99, "name": "C"}]}.

Here is my attempt but I'm not getting it right:

d = defaultdict(dict)
for l in (students, classes):
    for elem in l:
        d[elem['id']].update(elem)
l3 = d.values()
print(l3)

CodePudding user response:

Create a mapping id -> student dict. This way we can map ids present in classes['student'] to corresponding student dict.

id_to_student = {dct["id"]: dct for dct in students}
# {1: {'id': 1, 'name': 'A'},
#  2: {'id': 2, 'name': 'B'},
#  99: {'id': 99, 'name': 'C'},
#  4: {'id': 4, 'name': 'D'},
#  101: {'id': 101, 'name': 'E'}}

# Now update `classes` dict
for dct in classes:
    dct['students'] = [id_to_student[idx] for idx in dct['students']]

# [{'id': 1, 'students': [{'id': 1, 'name': 'A'}, {'id': 99, 'name': 'C'}]},
#  {'id': 2, 'students': [{'id': 1, 'name': 'A'}, {'id': 99, 'name': 'C'}, {'id': 101, 'name': 'E'}, {'id': 4, 'name': 'D'}]}, 
#  {'id': 3, 'students': [{'id': 4, 'name': 'D'}, {'id': 101, 'name': 'E'}]}]

CodePudding user response:

I've created an empty list new_classes to store the results in. Then I have iterated through each dict in the classes list. For each dict, I get the list in students using ids = dic['students'], then I use list comprehension to go thorugh each dict in students and check if the id matches one of the ids in the list, and if so keep it ([i for i in students if i['id'] in ids]) and replace the 'students' vale in that dict with the result. Then I append the whole updated dict to the new list. Full code:

new_classes = []
for dic in classes:
    ids = dic['students']
    dic['students'] = [i for i in students if i['id'] in ids]
    new_classes.append(dic)

Output:

[{'id': 1, 'students': [{'id': 1, 'name': 'A'}, {'id': 99, 'name': 'C'}]},
 {'id': 2,
  'students': [{'id': 1, 'name': 'A'},
   {'id': 99, 'name': 'C'},
   {'id': 4, 'name': 'D'},
   {'id': 101, 'name': 'E'}]},
 {'id': 3, 'students': [{'id': 4, 'name': 'D'}, {'id': 101, 'name': 'E'}]}]

CodePudding user response:

Maybe something like this

from copy import deepcopy
from pprint import pprint

students = [
    {"id": 1, "name": "A"},
    {"id": 2, "name": "B"},
    {"id": 99, "name": "C"},
    {"id": 4, "name": "D"},
    {"id": 101, "name": "E"},
]

classes = [
    {"id": 1, "students": [1, 99]},
    {"id": 2, "students": [1, 99, 101, 4]},
    {"id": 3, "students": [4, 101]},
]

_classes = deepcopy(classes)
for idx, classe in enumerate(classes):
    _classes[idx]['students'] = []
    for i in classe['students']:
        student = [x for x in students if x.get('id') == i]
        _classes[idx]['students'].append(student[0])
classes = _classes
pprint(classes)

Result

[{'id': 1, 'students': [{'id': 1, 'name': 'A'}, {'id': 99, 'name': 'C'}]},
 {'id': 2,
  'students': [{'id': 1, 'name': 'A'},
               {'id': 99, 'name': 'C'},
               {'id': 101, 'name': 'E'},
               {'id': 4, 'name': 'D'}]},
 {'id': 3, 'students': [{'id': 4, 'name': 'D'}, {'id': 101, 'name': 'E'}]}]
  • Related