2

I have a nested dictionary and I want to update the value of an item based on its key value. For example, I have the following dictionary and I want to set the value of every occurrence of an item with key=='p' to be 1.

my_dict = {'p': 0, 'nested_dict': {'p': 0, 'a': 2}}

For a regular dictionary (non-nested) the update method provides a simple one-liner solution:

my_dict.update((x, 1) for x, y in my_dict.items() if x=='p')

I'm looking for a similar solution for the case of nested dictionary

2
  • we are talking arbitrarily nested or is the max depth known? Commented Jun 21, 2021 at 7:55
  • arbitrary depth, I think this implies applying some kind of recursion Commented Jun 21, 2021 at 8:02

2 Answers 2

2

If the max depth of the dictionary is known and constant and the 'p's always appear at the same depth this can be solved without recursion. In all other cases, a recursive approach is needed. Based on the example problem and your comments, I will assume that the second one is true. Here is a recursive solution:

def setPto1(dct):
    return {k: setPto1(v) if isinstance(v, dict) else [v, 1][k=='p'] for k, v in dct.items()}

So you basically loop through the key-value pairs with a recursive dictionary comprehension. You were not far off with your approach. If there is something you do not understand about it, leave a comment.

If [v, 1][k=='p'] makes you feel uneasy, you can replace it with the more straight-forward (1 if k=='p' else v). They are the same thing.

Sign up to request clarification or add additional context in comments.

6 Comments

[v, 1][k=='p'] looks fancy-numpy-ish?
fancy sure, but I would not say numpyish; it is just basic boolean indexing. numpy has a much more powerful boolean indexing engine that operates similarly to filter.
Thanks!, personally, I like this [v, 1][k=='p'] style
Its a matter of taste as long as you understand it. Note however that it might be a bit more costly in terms of computer resources since Python needs to build the [v, 1] list. Feel free to accept the answer if it solves your problem.
@PatrickArtner This syntax, though requiring some adaptation, is quite nice. Since which version of python is it available? What's the exact name for this syntax?
|
0

Maybe this could get you started (you can still make it more generic, and it might have problems with repeated keys):

from functools import reduce

def decision_func(d, item, replace_on_item, replace_val):
    if item == replace_on_item:
        d[item] = replace_val
    else:
        return d[item]

my_dict = {'p': 0, 'nested_dict': {'p': 0, 'a': 2}}
reduce(lambda d, item: decision_func(d, item, 'p', ["some_other_val", 2]), ['nested_dict', 'p'], my_dict)
print(my_dict)

Output:

{'p': 0, 'nested_dict': {'p': ['some_other_val', 2], 'a': 2}}

What is done here is that you are going to run down the nesting tree by using the reduce function, and the decision_func is the one making the decision on whether to update a given entry or return the value for that key and continue looking for the next nesting level (basically a recursion prob). Note that as written above, this is not yet a bullet proof implementation.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.