I have string values as,
"a"
"a.b"
"b.c.d"
How to convert them into python dictionary variables as,
a
a["b"]
b["c"]["d"]
The first part of the string (before dot) will become the dictionary name and the rest of the substrings will become the dictionary keys
I ran into this same problem for parsing ini files with dot-delimited keys in different sections. e.g.:
[app]
site1.ftp.host = hostname
site1.ftp.username = username
site1.database.hostname = db_host
; etc..
So I wrote a little function to add "add_branch" to an existing dict tree:
def add_branch(tree, vector, value):
"""
Given a dict, a vector, and a value, insert the value into the dict
at the tree leaf specified by the vector. Recursive!
Params:
data (dict): The data structure to insert the vector into.
vector (list): A list of values representing the path to the leaf node.
value (object): The object to be inserted at the leaf
Example 1:
tree = {'a': 'apple'}
vector = ['b', 'c', 'd']
value = 'dog'
tree = add_branch(tree, vector, value)
Returns:
tree = { 'a': 'apple', 'b': { 'c': {'d': 'dog'}}}
Example 2:
vector2 = ['b', 'c', 'e']
value2 = 'egg'
tree = add_branch(tree, vector2, value2)
Returns:
tree = { 'a': 'apple', 'b': { 'c': {'d': 'dog', 'e': 'egg'}}}
Returns:
dict: The dict with the value placed at the path specified.
Algorithm:
If we're at the leaf, add it as key/value to the tree
Else: If the subtree doesn't exist, create it.
Recurse with the subtree and the left shifted vector.
Return the tree.
"""
key = vector[0]
tree[key] = value \
if len(vector) == 1 \
else add_branch(tree[key] if key in tree else {},
vector[1:],
value)
return tree
eval is fairly dangerous here, since this is untrusted input. You could use regex to grab the dict name and key names and look them up using vars and dict.get.
import re
a = {'b': {'c': True}}
in_ = 'a.b.c'
match = re.match(
r"""(?P<dict> # begin named group 'dict'
[^.]+ # one or more non-period characters
) # end named group 'dict'
\. # a literal dot
(?P<keys> # begin named group 'keys'
.* # the rest of the string!
) # end named group 'keys'""",
in_,
flags=re.X)
d = vars()[match.group('dict')]
for key in match.group('keys'):
d = d.get(key, None)
if d is None:
# handle the case where the dict doesn't have that (sub)key!
print("Uh oh!")
break
result = d
# result == True
Or even more simply: split on dots.
in_ = 'a.b.c'
input_split = in_.split('.')
d_name, keys = input_split[0], input_split[1:]
d = vars()[d_name]
for key in keys:
d = d.get(key, None)
if d is None:
# same as above
result = d
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With