Home > Mobile >  Select Python dict from list and modify it without affecting original list
Select Python dict from list and modify it without affecting original list

Time:10-19

I have a list of dictionaries, something like:

dict_list_all = [{'name': 'dict_00',
                    'steps': {'step_00': False,
                              'step_01': False,
                              'step_02': False},
                    },
                   {'name': 'dict_01',
                    'steps': {'step_00': False,
                              'step_01': False,
                              'step_02': False},
                    },
                   {'name': 'dict_01',
                    'steps': {'step_00': False,
                              'step_01': False,
                              'step_02': False},
                    },
                       ]

I want to select one of the dictionaries from this list, based on user input. Then, once this dictionary is selected, modify the boolean values under the 'steps' key in the selected dictionary, without affecting the original list.

I'm doing something like this

user_input = input('Which dict do you need?')
selected_dict = [d for d in dict_list_all if d['name'] == user_input][0]

At this point, I thought I was making a separated copy (selected_dict) of the dictionary I want from the list. However, when I modify the values in selected_dict, the corresponding values from the dictionary in dict_list_all are changed accordingly. How can I avoid this?

I tried using:

selected_dict = [d for d in dict_list_all if d['name'] == user_input][0].copy()
selected_dict = [d for d in dict_list_all.copy() if d['name'] == user_input][0].copy()

but the isseus remains, how can I fix this?

CodePudding user response:

You can use copy.deepcopy (and next with a generator):

from copy import deepcopy

selected_dict = next(deepcopy(d) for d in dict_list_all if d['name'] == user_input)

next has the advantage of saving memory (as in not building a list) and short-circuiting.

The shallow copy you get from your simple dict.copy will be a new top level dict object, but any values (we only care about mutable ones) like the nested dicts will remain references to the ones in the original.

CodePudding user response:

It sounds like you want a deep copy. Something like :

import copy
selected_dict = [copy.deepcopy(d) for d in dict_list_all.copy() if d['name'] == user_input][0]
  • Related