Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Iterate over all values in complex Dictionary

Goal: to add a ~tag to the tail end of any value, in a complex dictionary, with a % of occurrence.

Code works for "shallow" dictionaries (with no sub-dicts). I want to work with any complex dictionary.

Note: tag includes ~, if when it occurs.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel


Code:

import re
import random

RE_TAG = re.compile(r".+(~.+)")
DLM = '~'
tag_occurance = 25  # as %

thisdict =  {
  "Key1~tag": "foo",
  "Key2": "bar",
  "Key3~tag": {
    "Key3.1": "x",
    "Key3.2~tag": "y"
  }
}

def tag(_str):
    m = RE_TAG.match(_str)
    if m:
        return DLM + m[1][1:]  # '~tag'
    else:
        return ''

# Main Process
thisdict = {key: val + tag(key) if random.randint(0, 100) < tag_occurance else val for key, val in thisdict.items()}  # 25% tag

print(thisdict)  # view difference

Error:
val is its own a dictionary, hence error.

Traceback (most recent call last):
  File "./prog.py", line 25, in <module>
  File "./prog.py", line 25, in <dictcomp>
TypeError: unsupported operand type(s) for +: 'dict' and 'str'

Desired Output:

{
  "Key1~tag": "foo~tag",  # tag added as postfix concatenated string
  "Key2": "bar",
  "Key3~tag": {
    "Key3.1": "x",
    "Key3.2~tag": "y~tag"  # tag added as postfix concatenated string
  }
}

Cause of Error

thisdict.values() returns the sub-dicts. I’m only interested in their actual sub-values.

print(thisdict.values())
>>> dict_values(['foo', 'bar', {'Key3.1~tag': 'x', 'Key3.2~tag': 'y'}])

Desired iteration:

['foo', 'bar', 'x', 'y']

Please let me know if there is anything else I can add to post.

>Solution :

One approach, as mentioned in the comments, is to write a recursive function:

def nested_tag(d):
    res = {}
    for key, value in d.items():
        if isinstance(value, dict):
            res[key] = nested_tag(value)
        else:
            res[key] = value + tag(key) if random.randint(0, 100) < tag_occurance else value
    return res



final = nested_tag(this_dict)
print(final)

Output

{'Key1~tag': 'foo', 'Key2': 'bar', 'Key3~tag': {'Key3.1': 'x', 'Key3.2~tag': 'y~tag'}}

The above solution assumes the only complex values are dictionaries.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading