Python Forum

Full Version: nested dictionary
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi ,

I come from a perl background and used nested hash tables quite effectively and am unable to achieve the same using the python dictionary. Is it possible or not do something like this in python?

Reading a comma separated file into a deeply nested dictionary and printing it back out


inputfile = open('inputdata.csv','r')  # see bottom for the data file
count = 0
thisdict={}
#thisdict = {11:{12:{13:{14:{15:1}}}}}

for line in inputfile:
    line = line.rstrip("\n")
    items = line.split(",")
   
    if count != 0:
        thisdict[items[0]][items[1]][items[2]][items[3]][items[4]] = 1  ###this throws an error assignment is not acceptable
        pass
    count += 1

inputfile.close()


### the code below works if I am able to initialize the deeply nested dictionary using thisdict = {11:{12:{13:{14:{15:1}}}}}
    
print("number of lines read:", count)    
outfile = open('output2.txt','w')    
    
for col1 in thisdict:
    print(col1)
    for col2 in thisdict[col1]:
        print(col2)
        for col3 in thisdict[col1][col2]:
            print(col3)
            for col4 in thisdict[col1][col2][col3]:
                print(col4)
                for col5 in thisdict[col1][col2][col3][col4]: 
                    print(col5)
                    printline = str(col1) + "," +  str(col2) + "," + str(col3) + "," + str(col4) + "," + str(col5) + "," + str(thisdict[col1][col2][col3][col4][col5])  + "\n"
                    outfile.write(printline)
                
outfile.close()
#####inputdata.csv#####
Output:
col1,col2,col3,col4,col5 11,12,13,14,15 21,22,23,24,25 31,32,33,34,35 41,42,43,44,45 51,52,53,54,55 61,62,63,64,65 71,72,73,74,75 81,82,83,84,85
####end of inputdata.csv#######
Please use proper tags while posting a thread - see BBCode to know more
the only problem I see is that you are not checking to see if enough values are provided in line, or if a value is not a valid key
if the list created by the split contains at least 5 items, this should work.
Proof:
>>> mydict = {
...     'A': {
...         'B': {
...             'C': {
...                 'D': {
...                     'E': 'hello there'
...                 }
...             }
...         }
...     }
... }
>>> line = "A B C D E"
>>> line = line.strip().split()
>>> line
['A', 'B', 'C', 'D', 'E']
>>> mydict[line[0]][line[1]][line[2]][line[3]][line[4]]
'hello there'
>>>
There's a stackoverflow answer on creating a class that autovivifies dictionaries in a matter similar to perl.

https://stackoverflow.com/questions/6354...ctionaries
thanks - not sure if I am reading your solution correctly but I want to read from the file and dynamically create a nested dictionary without explicitly using the assignment you show below:

mydict = {
...     'A': {
...         'B': {
...             'C': {
...                 'D': {
...                     'E': 'hello there'
...                 }
...             }
...         }
...     }
... }
One can build such a dictionary from 'inside-out'. I have no idea in which data structures such dictionaries should be kept, so this code just prints them out:

with open('inputdata.csv') as f:
    header = next(f)
    for i, row in enumerate(f, start=1):
        nested_dict = i
        data = row.strip().split(',')
        for key in reversed(data):
              nested_dict = {int(key): nested_dict}
        print(nested_dict)
This will output:

Output:
{11: {12: {13: {14: {15: 1}}}}} {21: {22: {23: {24: {25: 2}}}}} {31: {32: {33: {34: {35: 3}}}}} {41: {42: {43: {44: {45: 4}}}}} {51: {52: {53: {54: {55: 5}}}}} {61: {62: {63: {64: {65: 6}}}}} {71: {72: {73: {74: {75: 7}}}}} {81: {82: {83: {84: {85: 8}}}}}
(May-28-2020, 04:15 PM)rkpython Wrote: [ -> ]thanks - not sure if I am reading your solution correctly but I want to read from the file and dynamically create a nested dictionary without explicitly using the assignment you show below:

That's what the autovivification class mentioned above does.

class Vividict(dict):
    """Per https://stackoverflow.com/questions/635483/what-is-the-best-way-to-implement-nested-dictionaries"""
    def __missing__(self, key):
        value = self[key] = type(self)() # retain local pointer to value
        return value                     # faster to return than dict lookup

thisdict = Vividict()
thisdict['A']['B']['C']['D'] = "leaf data"
print(thisdict)
Output:
{'A': {'B': {'C': {'D': 'leaf data'}}}}
Brilliant solution - exactly what I was looking for - thanks