How to create a nested dictionary from a text file

Viewed 77

So, my file looks like this :

Intestinal infectious diseases (001-003) 
001 Cholera
002 Typhoid and paratyphoid fevers
003 Other salmonella infections

Tuberculosis (004-006)
004 Primary tuberculous infection
005 Pulmonary tuberculosis
006 Other respiratory tuberculosis

.
.
.

I'm supposed to make a nested dictionary with the disease group as keys and the dictionary containing the disease code and name, as value for the first dictionary. I'm having some trouble separating the disease codes into their own disease groups. Here's what I've done so far:

import json

icd9_encyclopedia={}
lines = []    
f = open("icd9_info.txt", 'r')
for line in f:
    line = line.rstrip("\n")
    if line[0].isnumeric() == True:
        icd9_encyclopedia[line] = ??? 
        
    


f.close()
4 Answers

I used defaultdict to easily make a nested dictionary, as follows:

from collections import defaultdict

icd9_encyclopedia = defaultdict(dict)
disease_group = ""
with open("icd9_info.txt", 'r') as f:
    for line in [i[:-1] for i in f.readlines()]: # [:-1] to remove '\n' for each line
        if line == "": # skip if blank line
            continue
        if not line[0].isdigit():
            disease_group = line # temporarily save current disease group name for the following lines
        else:
            code, name = line.split(maxsplit=1)
            icd9_encyclopedia[disease_group][code] = name

for key, value in icd9_encyclopedia.items():
    print(key, value)
    
#Intestinal infectious diseases (001-003) {'001': 'Cholera', '002': 'Typhoid and paratyphoid fevers', '003': 'Other salmonella infections'}
#Tuberculosis (004-006) {'004': 'Primary tuberculous infection', '005': 'Pulmonary tuberculosis', '006': 'Other respiratory tuberculosis'}

You can see more detail about defaultdict here: https://www.geeksforgeeks.org/defaultdict-in-python/

Here's another take on the problem that uses just basic Python:

from pprint import pprint

icd9_encyclopedia={}

key = None
item = {}

with open("icd9_info.txt") as f:
    for line in f:
        line = line.strip()
        if not line[0].isdigit():
            # Start a new item
            if key:
                # Store the prior item in the main dictionary
                icd9_encyclopedia[key] = item
            # Initialize the new item
            key = line
            item = {}
        else:
            # A detail entry - add it to the current item
            num, rest = line.split(' ', 1)
            item[num] = rest

# Store the final item to the dictionary
if key:
    icd9_encyclopedia[key] = item

pprint(icd9_encyclopedia)

Result:

{'Intestinal infectious diseases (001-003)': {'001': 'Cholera',
                                              '002': 'Typhoid and paratyphoid '
                                                     'fevers',
                                              '003': 'Other salmonella '
                                                     'infections'},
 'Tuberculosis (004-006)': {'004': 'Primary tuberculous infection',
                            '005': 'Pulmonary tuberculosis',
                            '006': 'Other respiratory tuberculosis'}}

solution

import itertools
from pathlib import Path

# load text lines
lines = Path('data.txt').read_text().split('\n')

# build output dictionary
icd9_encyclopedia = {
    # build single group dictionary
    group_name: {
        int(code): disease_name
        # split each disease line into code and text name
        for disease_string in disease_strings
        for (code, _, disease_name) in [disease_string.partition(' ')]
    }
    # get groups separated by an empty line
    # isolate first item in each group as its name
    for x, (group_name, *disease_strings) in itertools.groupby(lines, bool) if x
}

result

{'Intestinal infectious diseases (001-003)': {1: 'Cholera',
                                              2: 'Typhoid and paratyphoid '
                                                 'fevers',
                                              3: 'Other salmonella infections'},
 'Tuberculosis (004-006)': {4: 'Primary tuberculous infection',
                            5: 'Pulmonary tuberculosis',
                            6: 'Other respiratory tuberculosis'}}

validInt checks weather the data is a valid integer

def validInt(data):
    try:
        int(data)
    except Exception as e:
        return False
        pass
    return True

encyclo = {}
with open("file.data",'r') as f:
    lines = f.readlines()
    for line in lines:
        if len(line.strip()) == 0:#line should not be empty
            continue
        first = line.split(' ')[0]
        if validInt(first):
            di = encyclo[list(encyclo.keys())[-1]] # returns a dictionary
            di[first] = line[len(first):] # inserting data to dictionary len(first) is used to skip the numeric part
        else:
            encyclo[line] = {}


for key, value in encyclo.items():#displaying data
    print(key, value)

$ python3 test.py
Intestinal infectious diseases (001-003) 
 {'001': ' Cholera\n', '002': ' Typhoid and paratyphoid fevers\n', '003': ' Other salmonella infections\n'}
Tuberculosis (004-006)
 {'004': ' Primary tuberculous infection\n', '005': ' Pulmonary tuberculosis\n', '006': ' Other respiratory tuberculosis\n'}
Related