4. Изменение элемента во вложенном списке без мутации исходных данных
Условие задачи:
Дан словарь, в одном из ключей которого хранится список. Нужно изменить один элемент этого списка так, чтобы исходный словарь и исходный список остались без изменений.
Требуется получить новый словарь с обновленным значением, не мутируя исходные структуры данных.
Спойлеры к решению
Подсказки
- Нельзя менять список напрямую через
data["key"][index] = value, потому что это изменит исходный список. - Обычная копия словаря через
data.copy()копирует только сам словарь, но вложенный список останется тем же объектом. - Нужно создать новый словарь.
- Для изменяемого списка нужно создать отдельную копию.
- После этого в новом словаре заменить старый список на обновлённый.
Решение
def update_list_item(data: dict, key: str, index: int, new_value) -> dict:
new_list = data[key].copy()
new_list[index] = new_value
new_data = data.copy()
new_data[key] = new_list
return new_data
Пример использования:
numbers = [1, 2, 3]
data = {
"name": "test",
"numbers": numbers
}
new_data = update_list_item(data, "numbers", 1, 99)
print(data) # {'name': 'test', 'numbers': [1, 2, 3]}
print(numbers) # [1, 2, 3]
print(new_data) # {'name': 'test', 'numbers': [1, 99, 3]}
Функция не мутирует исходный словарь и исходный список. Она создаёт копию вложенного списка, изменяет элемент уже в этой копии, затем создаёт новый словарь и кладёт туда обновлённый список.
Вариант через распаковку:
def update_list_item(data: dict, key: str, index: int, new_value) -> dict:
new_list = [
new_value if i == index else item
for i, item in enumerate(data[key])
]
return {
**data,
key: new_list
}