简体   繁体   中英

Creating a hierarchical dictionary with nested lists or dictionaries from 2 lists

I have 2 lists. The first has number denoting what part of the hierarchy that the value in the other list at the same index belongs. I am trying to get dynamic code that could theoretically go to any number of steps.

The first 3 work correctly but when I had more steps to the hierarchy I cant get a perfect return. I am just learning Python so if there are any suggestions to improve my ugly code as well I would appreciate it.

The first list is a list containing numbers. These numbers are the step within the hierarchy. The second list will be sorted based off the step value of the first list at their shared indexes.

below are 3 examples of what I am trying. The first 2 are correct but they only work for steps 0 and 1. I am trying to make the code to where it will work with any length of lists and any number range (the next steps can only be +/- 1).

output should look like this, using the first list showing the steps:

0
0
 1
 1
  2
   3
  2
  2
 1
0
 1
  2
   3
   3

I would like to set all 0 steps set to a dictionary of the value of the same index of the second list. This dictionary will contain either a nested list or nested dictionaries. I am not sure which is the better way to go for this.

I apologize for any confusion and thank you for any help.

#!/bin/usr/env python

from pprint import pprint

print('\n')

list1 = [0, 1, 0, 1, 1]
lista = ['a','b','c', 'd', 'e']
dict = {}
for index, value in enumerate(lista):
  inc = 1
  if (list1[index] == 0):
     dict[value] = []
     try:
        while (list1[index + inc] > 0):
            dict[value].append(lista[index + inc])
            inc += 1
     except IndexError:
        pass

pprint(dict)

print('\n' + '#'*150 + "\n")

list2 = [0, 1, 1, 1, 1, 0, 1]
listb = ['a','b','c','d','e', 'f', 'g']
dict = {}
for index, value in enumerate(listb):
   inc = 1
    if (list2[index] == 0):
        dict[value] = []
        try:
            while (list2[index + inc] > 0):
                dict[value].append(listb[index + inc])
                inc += 1
        except IndexError:
            pass

pprint(dict)

print('\n' + '#'*150 + "\n")

list3 = [0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 2]
listc = ['a', 'b', 'c', 'd', 'e' ,'f' , 'g', 'h', 'i', 'j', 'k', 'l', 'm' ,'n' ,'o' , 'p', 'q' ,'r' ,'s', 't', 'u', 'v', 'w', 'x']

dict = {}
temp_dict = {}
for index, value in enumerate(listc):
    inc = 1
    if (list3[index] == 0):
       dict[value] = []
        try:
            while (list3[index + inc] > 0):
                if (list3[index + inc] < list3[index + (inc + 1)]):
                    dict[value].append([listc[index + inc]])
                elif (list3[index + inc] == list3[index + (inc + 1)]):
                    dict[value].append()
                inc += 1
        except IndexError:
            pass

pprint(dict)

print('\n' + '#'*150 + "\n")

This is the current output.

{'a': ['b'], 'c': ['d', 'e']}

######################################################################################################################################################

{'a': ['b', 'c', 'd', 'e'], 'f': ['g']}

######################################################################################################################################################

{'a': [['b']], 'v': [['w']]}

######################################################################################################################################################

I am trying to get the third output to look like this.

{
'a': [ 'b', 
          [ 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u'], 
'v': [ 'w', 
          [ 'x']] 
}

Here's a solution. Note, that in addition to the actual result is returns how many items were consumed from the list. You can of course ignore that if you'd like.

def build_dict_from_lists(depth_list, item_list):
    if len(depth_list) != len(item_list):
        raise Exception("Canincompatible lengths")

    depth0 = depth_list[0]

    res = []
    next_index = 0
    while next_index < len(depth_list) and  depth_list[next_index] >= depth0:
        item = item_list[next_index]
        depth = depth_list[next_index]        
        if depth == depth0:
            res.append(item)
            next_index += 1
        else: 
            consumed, sub_res = build_dict_from_lists(depth_list[next_index:], item_list[next_index:])
            res.append(sub_res) 
            next_index += consumed 

    if depth0 == 0 and any(isinstance(x, list) for x in res): # switch the result from a dict to a list
        d = {}
        for inx in range(0, len(res), 2):
            key = res[inx]
            val = res[inx + 1]
            d[key] = val
        res = d 

    return next_index, res

A few tests to verify the correctness of the code:

assert build_dict_from_lists([0, 0, 0], ["a", "b", "c"]) == (3, ['a', 'b', 'c'])

assert build_dict_from_lists([0, 1, 2], ["a", "b", "c"]) == (3, {'a': ['b', ['c']]})
assert build_dict_from_lists([0, 1, 2, 1, 2], ["a", "b", "c", "d", "e"]) == (5, {'a': ['b', ['c'], 'd', ['e']]})

list3 = [0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 2]
listc = ['a', 'b', 'c', 'd', 'e' ,'f' , 'g', 'h', 'i', 'j', 'k', 'l', 'm' ,'n' ,'o' , 'p', 'q' ,'r' ,'s', 't', 'u', 'v', 'w', 'x']

expected = {'a': 
[ 'b', 
          [ 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u']], 
'v': [ 'w', 
          [ 'x']] 
}
assert build_dict_from_lists(list3, listc) == (24, expected)

list4 = [0, 1, 1,     2,   2, 2,   2, 1,  2, 1, ] 
listd = ['a','b','c','d','e','f','g','h','i','j'] 
assert build_dict_from_lists(list4, listd) == (10, {'a': ['b', 'c', ['d', 'e', 'f', 'g'], 'h', ['i'], 'j']})

list5 = [0,   1,  1,  2,  2,  3,  3,  1,  1,  2,  2,  3] 
liste = ['a','b','c','d','e','f','g','h','i','j','k','l'] 
assert build_dict_from_lists(list5, liste) == (12, {'a': ['b', 'c', ['d', 'e', ['f', 'g']], 'h', 'i', ['j', 'k', ['l']]]})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM