1

I'm trying to create a dictionary object like below using the input file data structure as below, During conversion inner object is being replicated. Any advise what fix is needed for desire output

input file data:/home/file1.txt

[student1]
fname       : Harry
lname       : Hoit
age         : 22

[Student2]
fname       : Adam
lname       : Re
age         : 25

expected output :

{'Student1' : {'fname' : 'Harry', 'lname' : 'Hoit', 'Age' : 22},
'Student2' : {'fname' : 'Adam', 'lname' : 'Re', 'Age' : 25}}
def dict_val():
    out = {}
    inn = {}
    path= '/home/file1.txt'
    with open(path, 'r') as f:
        for row in f:
            row = row.strip()
            if row.startswith("["):
                i = row[1:-1]
                # inn.clear() ## tried to clean the inner loop during second but its not correct
            else:
                if len(row) < 2:
                    pass
                else:
                    key, value = row.split('=')
                    inn[key.strip()] = value.strip()
                    out[i] = inn
    return out

print(dict_val())

current output: getting duplicate during second iteration

{'student1': {'fname': 'Adam', 'lname': 'Re', 'age': '25'}, 
 'Student2': {'fname': 'Adam', 'lname': 'Re', 'age': '25'}}
E88
  • 97
  • 1
  • 9

3 Answers3

1

With just a little change, you will get it. You were pretty close.

The modification includes checking for empty line. When the line is empty, write inn data to out and then clear out inn.

def dict_val():
    out = {}
    inn = {}
    path= 'file.txt'

    with open(path, 'r') as f:
        for row in f:
            row = row.strip()
            if row.startswith("["):
                i = row[1:-1]
                continue
            
            # when the line is empty, write it to OUT dictionary
            # reset INN dictionary
            if len(row.strip()) == 0:
                if len(inn) > 0:
                    out[i] = inn
                inn = {}
                continue
            
            key, value = row.split(':')
            inn[key.strip()] = value.strip()

    # if last line of the file is not an empty line and
    # the file reading is done, you can check if INN still
    # has data. If it does, write it out to OUT
    if len(inn) > 0:
       out[i] = inn

    return out

print(dict_val())
zedfoxus
  • 35,121
  • 5
  • 64
  • 63
0

When you do out[i] = inn you copy the reference/pointer to the inn dict. This means that when the inn dict is updated in the later part of the loop, your out[1] and out[2] point to the same thing.

to solve this, you can create deepcopy of the inn object.

ref : Nested dictionaries copy() or deepcopy()?

Manish Dash
  • 2,004
  • 10
  • 20
0

I would work the nested dictionary all at once since you're not going that deep.

def dict_val(file):
    inn = {}
    for row in open(file, 'r'):
        row = row.strip()
        if row.startswith("["):
            i = row[1:-1]
        elif len(row) > 2:
            key, value = row.split(':')
            inn[i][key.strip()] = value.strip()
    return inn

print(dict_val('/home/file1.txt'))
Kyle Hurst
  • 252
  • 2
  • 6