0

I have two files students and grades that has to be read and converted to a dictionary and finally print to a prettytable:

Grades:

10103   SSW 567 A   98765
10103   SSW 564 A-  98764
10103   CS 501  B   98764
10115   SSW 567 A   98765
10115   SSW 564 B+  98764

Students:

10103   Baldwin, C  SFEN
10115   Wyatt, X    SFEN

Below is the code to do that:

from collections import  defaultdict
from prettytable import PrettyTable
import os


class University:

    def __init__(self,path):
        self.students=dict()
        self.instructors=dict()             
        self.grades=defaultdict(list)
        

    def gg(self):
        for filename in os.listdir(self.path):
            with open(os.path.join(self.path, filename), 'r') as f:
                if filename=="students.txt":
                    for line in f:
                        
                        a,b,c = line.split("\t")
                        self.students[a] = {
                                "name": b, "major": c}
                
                elif filename=="grades.txt":
                    for line in f:
                        
                        d,e,f,g = line.split("\t")
                        self.grades[d].append({
                                "course": e, "grade": f,"instructor":g})
                        
                        
        pt: PrettyTable = PrettyTable(
            field_names=[
                'CWID',
                'Name',
                'cc',])    
        for i,j in self.students.items():
            for x,y in self.grades.items():
                if i==x:
                    pt.add_row([i,j["name"],y["course"]])

                
        return pt

a = University("C://Users/Swayam/Documents/Downloads")
c = a.gg()
print(c)

The output is supposed to be:

10103 Baldwin,C SSW567,SSW564,CS501
10115 Wyatt, X  SSW 567,SSW564

When I run the above code I get the below error:

TypeError: list indices must be integers or slices, not str

I am not supposed to use the variables in the add_row line and I know that, but what can I replace it with so I get the output.

Swayam Shah
  • 119
  • 1
  • 8

1 Answers1

0

The issue with your code is that y is a list:

for i,j in self.students.items():
    for x,y in self.grades.items():
        print(type(y))
>>> <class 'list'>

This is because of you code where you define grades:

self.grades=defaultdict(list)

So, you need some extra code to go through the list of dictionaries:

courses = ",".join(h["course"] for h in y)

And so, the final code becomes:

from collections import defaultdict
from prettytable import PrettyTable
import os


class University:
    def __init__(self, path):
        self.students = dict()
        self.instructors = dict()
        self.grades = defaultdict(list)
        self.path = path

    def gg(self):
        for filename in os.listdir(self.path):
            with open(os.path.join(self.path, filename), "r") as f:
                if filename == "students.txt":
                    for line in f:

                        a, b, c = line.split("\t")
                        self.students[a] = {"name": b, "major": c}

                elif filename == "grades.txt":
                    for line in f:

                        d, e, f, g = line.split("\t")
                        self.grades[d].append(
                            {"course": e, "grade": f, "instructor": g}
                        )

        pt: PrettyTable = PrettyTable(
            field_names=[
                "CWID",
                "Name",
                "cc",
            ]
        )

        for i, j in self.students.items():
            for x, y in self.grades.items():
                if i == x:
                    courses = ",".join(h["course"] for h in y)
                    pt.add_row([i, j["name"], courses])

        return pt


a = University("C://Users/Swayam/Documents/Downloads")
c = a.gg()
print(c)

I get this output when running the above code:

+-------+------------+------------------------+
|  CWID |    Name    |           cc           |
+-------+------------+------------------------+
| 10103 | Baldwin, C | SSW 567,SSW 564,CS 501 |
| 10115 |  Wyatt, X  |    SSW 567,SSW 564     |
+-------+------------+------------------------+

Note however that I did have to change:

  1. The split you were using to regex split since \t wasn't getting recognised for me
  2. Added self.path = path to your __init__ method
  3. Of course, the path too
Rolv Apneseth
  • 2,078
  • 2
  • 7
  • 19
  • This still leaves the j["name"] with the same error, I tried adding names = ",".join(h["name"] for h in j but it throws a key error – Swayam Shah Apr 12 '21 at 17:00
  • I included the full code now and the output I get, was this the code you were running? I had no issues with the `j['name']` since `j` should be a dictionary which does contain the key `name` – Rolv Apneseth Apr 12 '21 at 19:28