Modify the value of a multi-nested dictionary
Question:
What is the best way to access a multi-nested dictionary by its value and modify its value? The way that the value is modified must be by its current value. To explain better, the below example array myArr
has a nested dictionary with value c2
how can I access that dictionary and modify c2
into c2_edit
? The final output should look like editedArr
. What is the most efficient way to achieve this for a large array size? Thanks in advance
myArr = [{
"a1": [{
"b1": "c1"
}, {
"b2": "c2"
}]
}, {
"a2": [{
"b3": "c3"
}, {
"b4": "c4"
}]
}]
#expected output
editedArr = myArr = [{
"a1": [{
"b1": "c1"
}, {
"b2": "c2_edit"
}]
}, {
"a2": [{
"b3": "c3"
}, {
"b4": "c4"
}]
}]
Answers:
The easiest way to modify an arbitrarily nested object is generally a recursive function:
>>> def recursive_replace(obj, old_value, new_value):
... if obj == old_value:
... return new_value
... if isinstance(obj, dict):
... return {k: recursive_replace(v, old_value, new_value) for k, v in obj.items()}
... if isinstance(obj, list):
... return [recursive_replace(i, old_value, new_value) for i in obj]
... return obj
...
>>> myArr = [{
... "a1": [{
... "b1": "c1"
... }, {
... "b2": "c2"
... }]
... }, {
... "a2": [{
... "b3": "c3"
... }, {
... "b4": "c4"
... }]
... }]
>>> recursive_replace(myArr, "c2", "c2_edit")
[{'a1': [{'b1': 'c1'}, {'b2': 'c2_edit'}]}, {'a2': [{'b3': 'c3'}, {'b4': 'c4'}]}]
Other types of nested object (tuples, sets, or your own classes) can easily be added as additional if
blocks in the replacement function. The important thing is that each recursive call needs to apply the function to the object’s contents and return the modified object.
Pythonic 1-liner function:
def edit_any_value(arr, val, n_val):
return [{k: [{k: v if v != val else n_val for k, v in nd.items()} for nd in v]} for d in arr for k, v in d.items()]
This doesn’t modify the existing array, but it creates a new one with your modificated value.
I think creating new modified versions of one variable is always better than modifying it, but that’s just my opinion!
What is the best way to access a multi-nested dictionary by its value and modify its value? The way that the value is modified must be by its current value. To explain better, the below example array myArr
has a nested dictionary with value c2
how can I access that dictionary and modify c2
into c2_edit
? The final output should look like editedArr
. What is the most efficient way to achieve this for a large array size? Thanks in advance
myArr = [{
"a1": [{
"b1": "c1"
}, {
"b2": "c2"
}]
}, {
"a2": [{
"b3": "c3"
}, {
"b4": "c4"
}]
}]
#expected output
editedArr = myArr = [{
"a1": [{
"b1": "c1"
}, {
"b2": "c2_edit"
}]
}, {
"a2": [{
"b3": "c3"
}, {
"b4": "c4"
}]
}]
The easiest way to modify an arbitrarily nested object is generally a recursive function:
>>> def recursive_replace(obj, old_value, new_value):
... if obj == old_value:
... return new_value
... if isinstance(obj, dict):
... return {k: recursive_replace(v, old_value, new_value) for k, v in obj.items()}
... if isinstance(obj, list):
... return [recursive_replace(i, old_value, new_value) for i in obj]
... return obj
...
>>> myArr = [{
... "a1": [{
... "b1": "c1"
... }, {
... "b2": "c2"
... }]
... }, {
... "a2": [{
... "b3": "c3"
... }, {
... "b4": "c4"
... }]
... }]
>>> recursive_replace(myArr, "c2", "c2_edit")
[{'a1': [{'b1': 'c1'}, {'b2': 'c2_edit'}]}, {'a2': [{'b3': 'c3'}, {'b4': 'c4'}]}]
Other types of nested object (tuples, sets, or your own classes) can easily be added as additional if
blocks in the replacement function. The important thing is that each recursive call needs to apply the function to the object’s contents and return the modified object.
Pythonic 1-liner function:
def edit_any_value(arr, val, n_val):
return [{k: [{k: v if v != val else n_val for k, v in nd.items()} for nd in v]} for d in arr for k, v in d.items()]
This doesn’t modify the existing array, but it creates a new one with your modificated value.
I think creating new modified versions of one variable is always better than modifying it, but that’s just my opinion!