3

How would I turn a list like ["one","two","three","four"] into something like {"one": {"two": {"three":{"four"}}}} where each item in the list would be a descendant of the other element in the dictionary? I think it could be done in a recursive function, but I'm not sure how.

This is what I tried:

l = ["one","two","three","four"]
d = {}

for v in l[:-1]:
    d[v] = {l}
    d = d[v]

print(d)

Thanks!

Kremla
  • 87
  • 6
  • Note, you're last element is a *`set`* not a `dict`. – juanpa.arrivillaga Jul 24 '17 at 17:06
  • Since python doesn't have tail-call optimization, you'll probably want to refactor to non-recursive or properly handle when the length of the input is too long for recursion. See https://stackoverflow.com/questions/13591970/does-python-optimize-tail-recursion – Novaterata Jul 24 '17 at 17:07

4 Answers4

7

A recursive solution

def dictify(d):
    if len(d) == 1:
        return {d[0]}
    else:
        return {d[0]: dictify(d[1:])}

For example

>>> dictify(["one","two","three","four"])
{'one': {'two': {'three': {'four'}}}}

Note that the in above solution, the inner-most object is actually a set, not a dict. If you want all objects to be dict then you can modify the solution to

def dictify(d):
    if len(d) == 1:
        return {d[0]: None}
    else:
        return {d[0]: dictify(d[1:])}

Resulting in

>>> dictify(["one","two","three","four"])
{'one': {'two': {'three': {'four': None}}}}
Cory Kramer
  • 114,268
  • 16
  • 167
  • 218
3

If you wanted the structure to look like the following

{'one': {'two': {'three': {'four': None}}}}

You could generate that with something like this. This solution uses recursion.

arr = ["one", "two", "three", "four"]


def gen(arr):
    if len(arr) == 0:
        return None
    else:
        key = arr.pop(0)
        val = gen(arr)

        dict = {}
        dict[key] = val
        return dict

print gen(arr)
Kulix
  • 444
  • 3
  • 12
2

If you'd prefer a non-recursive solution:

def endeepen(lst):
    old = None
    for v in lst[::-1]:
        ret = {}
        ret[v] = old
        old = ret
    return ret

Just iterates the list in reverse and buries the each dct as the previous elements value:

>>> endeepen(l)
{'one': {'two': {'three': {'four': None}}}}

If you really want the last element to be a set, you can do so with a minor correction:

def endeepen(lst):
    old = {lst[-1]}
    for v in lst[len(lst) - 2::-1]:
        ret = {}
        ret[v] = old
        old = ret
    return ret

which then gives:

>>> endeepen(l)
{'one': {'two': {'three': set(['four'])}}}

Note: In both cases, I haven't covered edge conditions, so empty or very short lists len(1) <= 1 may misbehave.

TemporalWolf
  • 7,727
  • 1
  • 30
  • 50
0
l = ["one","two","three","four"]
d = {}

d2 = d
for v in l[:-1]:
    d2[v] = {}
    d2 = d2[v]
d2[l[-2]] = {l[-1]}
print(d)
>>> {'one': {'two': {'three': {'three': {'four'}}}}}
jdehesa
  • 58,456
  • 7
  • 77
  • 121