-1

The British GSCE grading system has recently changed and has got confusing and it just doesn't work. I just got my estimated grades and did not know what was good and what wasn't. To help my confusion I decided to make something to save, convert and edit my grades. To make my code neater I decided to use two for loops so it just prints them all out. When I tried this it looked like it was working but it just printed "For English language, you got 6c" then when it moved on to what was meant to be English literature it just printed "For English language, you got 6c", I did get 6c but the subject is not English language. The same happens if I rearrange the order of the for loops only the grades are the same but the lessons were normal.

All I've done is rearranged the for loops. Nothing seems to work. Here is the code:

            import time

            with open('lessons.txt', 'r') as f:
                english_language = str(f.readline().strip('\n'))
                english_lit = str(f.readline().strip('\n\n'))
                maths = str(f.readline().strip('\n\n\n'))
                chemistry = str(f.readline().strip('\n\n\n\n'))
                physics = str(f.readline().strip('\n\n\n\n\n'))
                biology = str(f.readline().strip('\n\n\n\n\n\n'))
                re = str(f.readline().strip('\n\n\n\n\n\n\n'))
                business = str(f.readline().strip('\n\n\n\n\n\n\n\n'))
                computer_science = str(f.readline().strip('\n\n\n\n\n\n\n\n\n'))
                french = str(f.readline().strip('\n\n\n\n\n\n\n\n\n\n'))
                geography = str(f.readline().strip('\n\n\n\n\n\n\n\n\n\n\n'))

            lessons = []
            lessons.extend((english_language, english_lit, maths, chemistry, physics, biology, re, business, computer_science, french, geography))
            lesson_name = ["English langauge", "English liturature", "Maths", "Chemistry", "Physics", "Biology", "R.E", "Business studies", "Computer science", "French", "Geography"]

            print("What do you want to do? Read your grades, edit your grades, convert your grades or read and convert your grades.")
            option = input("Say read to read your grades or edit to edit your grades: ")

            if option == "read":
                for i in lessons:
                    for name in lesson_name:
                        print("For", name, "you got",i)
                        time.sleep(3)
                        break

            elif option == "convert":
                import converter.py

            elif option == "edit":
                print("HIIIIIIIIIIIIIIIIIIII")

In the files are grades spanning from 5B, being the lowest I got, to 7B is the highest I got.

What I expect it to do is ask you what you want to do, which it does. Then if you enter 'read' it will say 'For English language, you got 6c' and repeat until it gets to Geography.

luckyjd
  • 9
  • 6

1 Answers1

-1

Two for loops do not make sense - the break is wierd as well :

for i in lessons:
    for name in lesson_name:
        print("For", name, "you got",i)
        time.sleep(3)     # 
        break             # this breaks after the first name every time

You can iterate both lists at once using something like:

nums = [1,2,3]
for idx,value in enumerate(["A","B","C"]):
     print("For", value, "you got", nums[idx])

or better by zipping it - see below for fixed dataparsing and postprocessing.


You can simplify your reading a lot by ignoring newlines and then convert the remaining grades into a dictionary using zip():

Create a file with newlines in it (and too many values):

import random

gr = [ f'{num}{let}' for num in range(1,10) for let in "ABC"]

with open('lessons.txt', 'w') as f:
    for k in random.choices(gr,k=20):
        f.write(k+"\n\n\n")

Read file and decomposit the list

with open('lessons.txt', 'r') as f:
    # read all lines, remove newlines, create a list of results
    grades = [x.strip() for x in f.readlines() if x.strip()]

# there are 20 scores in the file *_ takes all that are not named decomps: 

english_language, english_lit, maths, chemistry, physics, biology, re, \
business, computer_science, french, geography, *remainder = grades

print(english_language, english_lit, maths, chemistry, physics, biology, re, \
      business, computer_science, french, geography )

Output (3 runs):

3C 6A 9B 7B 8B 5A 2B 8C 7B 3A 9B
1C 8A 5A 1C 3A 9B 7C 9A 7B 7A 1A
4C 1A 4C 8B 9A 3C 2C 7B 7C 5B 2A

Create a lookup dict for lessons and grades:

You can tie the grades to the lesson_name using zip():

# order the same as in the 
lesson_name = ["English langauge", "English liturature", "Maths", "Chemistry",
               "Physics", "Biology", "R.E", "Business studies", "Computer science", 
               "French", "Geography", "Remainder"]

# dict comprehension to build the dictionary mapping lesson names to grades
grades = {k:v for k,v in zip(
    lesson_name,
    [english_language, english_lit, maths, chemistry, physics, biology, re,  
     business, computer_science, french, geography, remainder])}

print (grades) 

Output:

{'English langauge': '4B', 'English liturature': '3C', 'Maths': '1C', 
 'Chemistry': '8C', 'Physics': '6B', 'Biology': '2B', 'R.E': '6C',
 'Business studies': '8C', 'Computer science': '4B', 'French': '3A', 
 'Geography': '2A', 
 'Remainder': ['7B', '1A', '1C', '3B', '2B', '8B', '5B', '6B', '8C']}

You can use the dict to lookup grades by name:

print(grades["English langauge"]) # 4B

To print all things:

for name, grade in grades.items():
    print("For", name, "you got", grade) 
    # do not break here- this will end the loop!

Some explanations:

grades = [x.strip() for x in f.readlines() if x.strip()]

The whole list comp reads all lines of your file, discards empty lines and lines that only consist of whitespaces (space, tabs, newlines,..) - the remaining lines are put into the list grades but stripped first so the do not have any beginning/ending whitespaces.

  • zip() takes multiple iterables and pairs them up into tuples - for as long ans the shortest iterable is:

k = zip( [1,2,3],["a","b"],"!$&(=" )  #  [(1, 'a', '!'), (2, 'b', '$')]

results in:

(1, 'a', '!')   # every 0th element
(2, 'b', '$')   # every 1st element and nothing more because ["a","b"] has no 2nd element

Applying this to your data, I am zipping together a list of your single grades and the "strings" of the lecture_names to get:

[('English langauge', '5B'), ('English liturature', '8B'), ('Maths', '1C'), 
 ('Chemistry', '4B'), ('Physics', '4C'), ('Biology', '9A'), ('R.E', '6B'), 
 ('Business studies', '8A'), ('Computer science', '1A'), ('French', '8C'), 
 ('Geography', '9B'), 

 ('Remainder', ['7A', '4C', '6C', '5B', '3B', '9C', '3B', '1A', '3B'])]

and use that in a dict-comprehension to create a dictionary:

grades = {k:v for k,v in zip(
    lesson_name,
    [english_language, english_lit, maths, chemistry, physics, biology, re,  
     business, computer_science, french, geography, remainder])}

k and v are decompositions of one zip-result-tuple - the dict comprehensions creates a dictionary from them:

ex = {k:v for k,v in [ ("a",1), ("b",2) ] }  # simplified example

returns ex as dictionary {"a":1, "b":2}.

HTH

Patrick Artner
  • 50,409
  • 9
  • 43
  • 69
  • Thank you so much! This works very well and just liked I wanted. I have edited it a bit so it doesn't choose random grades and the remainder. But except from that, it works fine. Do you mind explaining it so I could understand what the code does? If not that's fine. – luckyjd Jan 15 '19 at 16:54
  • 1
    I don't know but maybe the downvote is because you don't answer the question, but solve the problem with totally new code? – Stefan Jan 15 '19 at 20:39