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.
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.
CodePudding user response:
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.