1

I have a string which I want to convert to a nested dictionary in Python.

Example Input :

import copy
diff_str = "/pathConstraint/latency/latencyValue"
value = "low"
diff_arr = diff.split("/")
final_temp_dict = dict()
for elem in reversed(diff_arr):
    if len(final_temp_dict) == 0:
        final_temp_dict.setdefault(elem, value)
    else:
        temp_final_dict = copy.deepcopy(final_temp_dict)
        final_temp_dict.setdefault(elem, temp_final_dict)
    print (final_temp_dict)

While running this I face an error and I'm not getting the expected output.

The output needed is as a nested dictionary:

{"pathConstraint" : {"latency" : {"latencyValue" : "low"}}}
CDJB
  • 14,043
  • 5
  • 29
  • 55
Scientist
  • 1,458
  • 2
  • 15
  • 31

5 Answers5

3

You could use the following recursive function:

def string_to_dict(keys, value):
    key = keys.split('/')
    if len(key) == 2:
        return {key[1]: value}
    else:
        return string_to_dict('/'.join(key[:-1]), {key[-1]: value})

Output:

>>> string_to_dict(diff_str, value)
{'pathConstraint': {'latency': {'latencyValue': 'low'}}}

Note that this assumes that diff_str begins with a / character.

CDJB
  • 14,043
  • 5
  • 29
  • 55
1

The following is an iterative approach. Note diff_arr[1:] is used to exclude the empty string that is generated from splitting on the initial /.

diff_str = "/pathConstraint/latency/latencyValue"
value = "low"
diff_arr = diff_str.split("/")
for key in list(reversed(diff_arr[1:])):
    value = {key: value}
print(value)

Output

{'pathConstraint': {'latency': {'latencyValue': 'low'}}}
Kent Shikama
  • 3,910
  • 3
  • 22
  • 55
1

Shorter recursive approach:

def to_dict(d, v):
  return v if not d else {d[0]:to_dict(d[1:], v)}


diff_str = "/pathConstraint/latency/latencyValue"
value = "low"
print(to_dict(list(filter(None, diff_str.split('/'))), value))

Output:

{'pathConstraint': {'latency': {'latencyValue': 'low'}}}
Ajax1234
  • 69,937
  • 8
  • 61
  • 102
0

I tried to modify your function as little as possible, this should work just fine

import copy
def func():
    diff_str = "/pathConstraint/latency/latencyValue"
    value = "low"
    diff_arr = diff_str.split("/")
    final_temp_dict = dict()
    for elem in reversed(diff_arr):
        if elem == "":
            continue
        if len(final_temp_dict) == 0:
           final_temp_dict[elem] = value
        else:
           temp_final_dict = copy.deepcopy(final_temp_dict)
           final_temp_dict = {}
           final_temp_dict[elem] = temp_final_dict

    print (final_temp_dict)

However, there are much nicer ways to do something like this. See the other answers for inspiration.

DanDayne
  • 154
  • 6
0
def convert(items, value):
    if not items:
        return value

    return {items.pop(0): convert(items, value)}


print(convert(diff_str.strip('/').split('/'), 'low'))
LinnTroll
  • 705
  • 4
  • 10