Looping to Create Nested Dictionary - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: Homework (https://python-forum.io/forum-9.html) +--- Thread: Looping to Create Nested Dictionary (/thread-6966.html) Pages:
1
2
|
Looping to Create Nested Dictionary - gngu2691 - Dec-15-2017 Hello! My code is supposed to read lines from a file that contains several attributes: assignment number, assignment name, grade, total, and weight. Each line of the file has this format. My code reads the lines and turns it into a nested dictionary. Currently, the code seems to be looping and overwriting the key values of the inner dictionary. Here is the file it's reading from: 1 assignment_1 85 100 0.25 2 test_1 90 100 0.25 3 exam_1 95 100 0.5The code should return a nested dictionary with the assignment name as the key, and the inner dictionary having the keys "number", "grade", "total", and "weight" for each line. The correct output: Here is my code:def reader(filename): file_reader = open(filename) results = [] innerdict = {} outerdict = {} for line in file_reader: parts = line.split(" ") line_tuple = (int(parts[0]), parts[1], int(parts[2]), int(parts[3]), float(parts[4])) key = line_tuple[1] outerdict[key] = innerdict innerdict["number"] = line_tuple[0] innerdict["grade"] = line_tuple[2] innerdict["total"] = line_tuple[3] innerdict["weight"] = line_tuple[4] return outerdictIt returns this output: I believe I am somewhat close, I just do not know how to preserve the values of the inner dictionary once it loops over a line. Thank you for your help! I've been trying to figure this out for a few days and just wish to understand. RE: Looping to Create Nested Dictionary - squenson - Dec-15-2017 This exercise is excellent to help the student understand that Python never copies objects but simply assign a pointer to the source object. So, when you execute outerdict[key] = innerdict , the content of outerdict[key] is not the hard values but simply a pointer to innerdict and when you modify innerdict a few statements below, of course the value of outerdict[key] is automatically modified.You need to copy the hard values of the dictionary innerdict to make them independent of innerdict. RE: Looping to Create Nested Dictionary - wavic - Dec-15-2017 Hm! Is it allowed dictionary comprehension? Open the file and read it with the readlines method. This will create a list of the lines. Create an empty dict for the final result. Iterate over the lines and for each line: split the line the_dict[splited_line[0]] = dict(zip(['number','grade','total','weight'], splited_line[1:]))Done. Of course, you will have to turn the digits from string to integers somewhere in the loop RE: Looping to Create Nested Dictionary - gngu2691 - Dec-16-2017 Squenson: I vaguely understand! How could I copy and save the values of innerdict to make them independent of the dictionary? Wavic: I implemented the line you gave me and it worked for a second, but now it pulls up a ValueError. Here's the updated code: def reader(filename): file_reader = open(filename) results = [] innerdict = {} outerdict = {} for line in file_reader: parts = line.split(" ") parts = line.replace("\n", "") line_tuple = (int(parts[0]), parts[1], int(parts[2]), int(parts[3]), float(parts[4])) key = line_tuple[1] # innerdict["number"] = line_tuple[0] # innerdict["grade"] = line_tuple[2] # innerdict["total"] = line_tuple[3] #innerdict["weight"] = line_tuple[4] outerdict[parts[1]] = dict(zip(['number','grade','total','weight'], parts[1:])) #outerdict[key] = innerdict return outerdict file_reader.close()And here's the error:
(Dec-15-2017, 11:04 PM)wavic Wrote: Hm! Is it allowed dictionary comprehension? Hi Wavic, I've almost gotten it! The only problem left with it is that 'number' in the inner dictionary has the wrong value. The line of code you helped me with is from index 1, everything is right except for the value of 'number', which is given the parts[1]when that is the key for the larger dictionary. Is there a way to get all of the indices excluding parts[1]? Here's the code: def reader(filename): file_reader = open(filename) results = [] innerdict = {} outerdict = {} for line in file_reader: line = line.replace("\n", "") parts = line.split(" ") line_tuple = (int(parts[0]), parts[1], int(parts[2]), int(parts[3]), float(parts[4])) key = line_tuple[1] # innerdict["number"] = line_tuple[0] # innerdict["grade"] = line_tuple[2] # innerdict["total"] = line_tuple[3] #innerdict["weight"] = line_tuple[4] outerdict[parts[1]] = dict(zip(['number','grade','total','weight'], parts[1:])) #outerdict[key] = innerdict return outerdictHere's the output. It's so close!
RE: Looping to Create Nested Dictionary - squenson - Dec-16-2017 Let's go back to your initial code and initial output outerdict[key] = innerdict innerdict["number"] = line_tuple[0] innerdict["grade"] = line_tuple[2] innerdict["total"] = line_tuple[3] innerdict["weight"] = line_tuple[4]From the output, we see that we have the right data of the third record, three times. This is "normal" because, as I said, the keys of outerdict point to innerdict and not its hard values. Let's slightly reorganize the code by first populating innerdict, then assign it to the outerdict: innerdict["number"] = line_tuple[0] innerdict["grade"] = line_tuple[2] innerdict["total"] = line_tuple[3] innerdict["weight"] = line_tuple[4] outerdict[key] = innerdictAnd finally, how to tell python to copy the hard values of innerdict? You can use the following way: outerdict[key] = dict(innerdict)(Note: to be fully correct, this statement is OK for making a copy of a "simple" dictionary which itself doesn't contain any complex objects like a list or a dictionary. For such cases, do a research on "copy" and "deepcopy") RE: Looping to Create Nested Dictionary - wavic - Dec-16-2017 Well, I didn't realize that the numbers are not the line numbers copied from your editor but data. Do it by hand. You have to do some changes since the slicing is totally wrong. # bellow this line add a for loop outerdict[parts[1]] = dict(zip(['grade','total','weight'], parts[2:])) # get rid of the 'number' in zip() arguments. Indices are changed a bit for line in file: items = line.split() outerdict[items[1]]['number'] = items[0] RE: Looping to Create Nested Dictionary - swarup19 - Jun-22-2018 import re out='''1 assignment_1 85 100 0.25 2 test_1 90 100 0.25 3 exam_1 95 100 0.5''' innerdict = {} outerdict = {} parts_1 = out.split("\n") for line in parts_1: parts = line.split(" ") line_tuple = (int(parts[0]), parts[1], int(parts[2]), int(parts[3]), float(parts[4])) key = line_tuple[1] outerdict[key] = dict(innerdict) outerdict[key]={'Total':'{0}'.format(parts[3]),'Number':'{0}'.format(parts[0]),'Grade':'{0}'.format(parts[2]),'Weight':'{0}'.format(parts[4])} print(outerdict) output: You can try this.
RE: Looping to Create Nested Dictionary - volcano63 - Jun-22-2018 In short - don't init innerdict outside of the loopouterdict = {} for line in file: parts = line.split(" ") outerdict[parts[1]] = {} ......As simple as that RE: Looping to Create Nested Dictionary - anickone - Jun-22-2018 This is done as follows. def reader(filename): with open(filename) as fin: txt = fin.read() lines=txt.strip().split('\n') outerdict={} for line in lines: lst=line.split() outerdict[lst[1]]={ 'number' : int(lst[0]), 'grade' : int(lst[2]), 'total' : int(lst[3]), 'weight' : float(lst[4]), } return outerdict RE: Looping to Create Nested Dictionary - volcano63 - Jun-22-2018 (Jun-22-2018, 08:47 AM)anickone Wrote: This is done as follows. While in-loop code makes the most sense of what I have seen above, separating file iteration and loop makes no sense. BTW, there's str.splitlines method
|