3
\$\begingroup\$

I have a value test-1 and a list of keys as below:

[
 ["initial", "short_title"],
 ["later", "datasets", "item_okmiwt"],
 ["general_title"]
]

I wanted the resulting dictionary like this:

{'initial': {'short_title': 'test-1'}, 'later': {'datasets': {'item_okmiwt': 'test-1'}}, 'general_title': 'test-1'}

I have written the following code for implementing the above result:

def set_copy_to_attr(value, copy_to_attr):
 """Method to copy value to copy_to config."""
 def build_nested_dict(element, result={}):
 if len(element) == 1:
 result[element[-1]] = pid_value
 return result
 else:
 for el in element:
 result[el] = {}
 element.remove(el)
 build_nested_dict(element, result[el])
 for _element in copy_to_attr:
 _dict = build_nested_dict(_element)
 if _dict:
 return _dict

I am getting the desired result, Is this approach can be optimized more?

200_success
145k22 gold badges190 silver badges478 bronze badges
asked Aug 24, 2022 at 10:07
\$\endgroup\$

1 Answer 1

5
\$\begingroup\$

Broadly: this kind of dictionary soup is a problem, and is often evidence of inadequate domain modelling and deserialisation. But you haven't shown enough of your actual application to say more.

Two things will slow you down: mutating element via .remove(), and recursing. Python is bad at recursing, and for input of sufficient depth this will easily blow the stack.

Add PEP484 type hints - even though, since this is dictionary soup, typing is made more difficult.

Rather than _dict (making it look like a private), typically to avoid Python keywords, the underscore is a suffix i.e. dict_.

Suggested

from pprint import pprint
from typing import Any, Iterable
def set_copy_to_attr(
 value: Any,
 copy_to_attr: Iterable[Iterable[Any]],
) -> dict:
 dict_ = {}
 for *values, leaf in copy_to_attr:
 nested = dict_
 for v in values:
 nested[v] = nested = {}
 nested[leaf] = value
 return dict_
def test() -> None:
 copy_to_attr = [
 ["initial", "short_title"],
 ["later", "datasets", "item_okmiwt"],
 ["general_title"]
 ]
 copied = set_copy_to_attr('test-1', copy_to_attr)
 pprint(copied)
if __name__ == '__main__':
 test()

Output

{'general_title': 'test-1',
 'initial': {'short_title': 'test-1'},
 'later': {'datasets': {'item_okmiwt': 'test-1'}}}
answered Aug 24, 2022 at 11:44
\$\endgroup\$
1
  • \$\begingroup\$ Thanks for the suggestions, for more context, the logic is to add metadata on the basis of some schema config and it is for showing some default values in the UI. \$\endgroup\$ Commented Aug 24, 2022 at 12:48

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.