Search code examples
pythonlistloopsdictionaryio

How to break for loop at the end of a line


Task at hand here is to create a dictionary using specified inputs.

First element is key and following elements are values.

Input:

name, George Mason
pa, 100.0, 100.0, 95.0, 95.0, 97.0
lab, 100.0, 100.0, 100.0, 0.0, 100.0
zy, 100.0, 100.0, 100.0, 100.0, 100.0
mid1, 90.0
mid2, 80.0
final, 85.0

Expected output, if project = False:

{'name': 'George Mason',
 'pa': [100.0, 100.0, 95.0, 95.0, 97.0],
 'lab': [100.0, 100.0, 100.0, 0.0, 100.0],
 'zy': [100.0, 100.0, 100.0, 100.0, 100.0],
 'mid1': 90.0, 'mid2': 80.0, 'final': 85.0}

Expected output, if project = True:

{'name': 'George Mason',
 'pa': [100.0, 100.0, 95.0, 95.0, 97.0, 97.4, 97.4, 97.4, 97.4],
 'lab': [100.0, 100.0, 100.0, 0.0, 100.0, 80.0, 80.0, 80.0, 80.0,
80.0, 80.0],
 'zy': [100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0,
100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0],
 'mid1': 90.0, 'mid2': 80.0, 'final': 85.0}

"If project is True and there are fewer than 9 programming assignments, 11 labs, or 15 zyBooks, you will need to project values for all of the missing grades (you do not need to consider the case where there are more grades). To do this for a given assignment type, compute the average grade for that assignment type, and then add copies of that average to the end of the given grade values so that that assignment type has the correct number of grades. For example, if the file had the following line "pa, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0", then there are only 7 programming assignment grade values. If project were True, you would compute the average of the given grades ((1.0+2.0+3.0+4.0+5.0+6.0+7.0)/7 = 4.0), and add that to the end of the list of grade values, so that the dictionary's value for the key "pa" would be the list [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 4.0, 4.0]."

I haven't even reached the True section. Right now I am trying to figure out how to get rid of the KeyError: ('name', 'Carl F. Gauss\n'). I am assuming that it is because the code doesn't know to move on to the next line once it reaches the end of the first. How would I do that?

My code is currently:

def read_grades_file(filename, project=False):
    file = open(filename, 'r')
    grade_dict = {}
    if project == False:
        for line in file.readlines():
            values = [line.split(', ')]
            key = tuple(values[0])
            val = values[1:]
            grade_dict[key].append(val)
    if project == True:
        for line in file.readlines():
            values = [line.split(', ')]
            key = tuple(values[0])
            val = values[1:]
    return grade_dict
        
print(read_grades_file('gauss.grades', project=False))

Solution

  • Here's a suggestion for the first part (which is the basis for the second):

    def read_grades_file(filename, project=False):
        grade_dict = {}
        with open(filename, 'r') as file:
            for line in file:
                key, *values = line.strip().split(', ')
                if key in {'pa', 'lab', 'zy'}:
                    grade_dict[key] = list(map(float, values))
                else:
                    value = values[0]
                    if key in {'mid1', 'mid2', 'final'}:
                        value = float(value)
                    grade_dict[key] = value
        if project:
            pass
        return grade_dict
    

    Iterating through the lines of the file

    • .strip() the line to get rid of whitespace, especially at the end ('\n')
    • .split(', ') it and unpack the resulting list in its first item key and the remaining items values
    • if the key is pa, lab, or zy convert values into a list of floats and assign it to key
    • otherwise extact the remaining item of values into the variable value, convert it into float if key is mid1, mid2, or final, and assign it to key.

    Result for input

    name, George Mason
    pa, 100.0, 100.0, 95.0, 95.0, 97.0
    lab, 100.0, 100.0, 100.0, 0.0, 100.0
    zy, 100.0, 100.0, 100.0, 100.0, 100.0
    mid1, 90.0
    mid2, 80.0
    final, 85.0
    

    is

    {'name': 'George Mason',
     'pa': [100.0, 100.0, 95.0, 95.0, 97.0],
     'lab': [100.0, 100.0, 100.0, 0.0, 100.0],
     'zy': [100.0, 100.0, 100.0, 100.0, 100.0],
     'mid1': 90.0,
     'mid2': 80.0,
     'final': 85.0}
    

    Regarding the second part: Check if the lists have the required minimum length. If not, calculate the average of the present items (e.g. use sum, math.fsum, or statistics.mean) and .extend() the lists with the average to meet the minimum length requirement. (Let me know if you need help.)