I have a list consisting of 4 attributes: subject, test, score, and result. I need to calculate the total score for each subject, by adding up the test scores for each subject. I currently have that. But I need to calculate the total test score of passed tests, and then divide that number by the total test score of all tests.
This is the first part of the code that works correctly:
from collections import defaultdict
d = defaultdict(float)
dc = defaultdict(float)
subject = ['Math', 'Math', 'Math', 'Math', 'Biology', 'Biology', 'Chemistry']
test = ['Test 1','Test 2','Test 3','Test 4','Test 1','Test 2','Test 1']
score = ['1.0', '0.0', '4.0', '0.0', '4.0', '6.0', '2.0']
result = ['fail', 'fail', 'pass', 'fail', 'fail', 'pass', 'pass']
points = [float(x) for x in score]
mylist = list(zip(subject, test, points, result))
for subject, test, points, completion, in mylist:
d[subject] = points
dc[(subject, test)] = points
print(d)
Expected result & actual result is:
{'Math': 5.0, 'Biology': 10.0, 'Chemistry': 2.0}
Now the issue I'm having is I need to add up the total number of points for each subject on only the tests that have been passed. And then divide that number from the total number of all tests (passed and failed) in a subject. So something like, 'if result == "passed" then do 'rest of calculations'.
This is the remaining code:
dc = {f"{subject} {test}" : round(points / d[subject], 2)
if d[subject]!=0 else 'division by zero'
for (subject, test), points in dc.items()}
print(dc)
Expected result:
Math: 4/5, Biology: 6/10, Chemistry: 2/2
Actual result:
'Math Test 1': 0.2, 'Math Test 2': 0.0, 'Math Test 3': 0.8, 'Math Test 4': 0.0, 'Biology Test 1': 0.4, 'Biology Test 2': 0.6, 'Chemistry Test 1': 1.0
CodePudding user response:
dapssed=defaultdic(float)
for subject, test, points, completion, in mylist:
d[subject] = points # this is the total passed and not passed
dc[(subject, test)] = points
if completition == 'pass':
dpassed[subject]= =points # Only pass point
CodePudding user response:
You want to add to the total in dc
only if the test is passed, so why not do that in the first place?
for sub, scr, completion, in zip(subject, score, result):
points = float(scr)
d[sub] = points
if completion == "pass":
dc[sub] = points
Now, you have
d = defaultdict(float, {'Math': 5.0, 'Biology': 10.0, 'Chemistry': 2.0})
dc = defaultdict(float, {'Math': 4.0, 'Biology': 6.0, 'Chemistry': 2.0})
To get your required output from here, just loop over the keys of d
, format the corresponding values from d
and dc
into a string, and print:
for sub, total_score in d.items():
print(f"{sub}: {dc[sub]} / {total_score}")
which gives:
Math: 4.0 / 5.0
Biology: 6.0 / 10.0
Chemistry: 2.0 / 2.0
To remove the decimal point, see Formatting floats without trailing zeros
Note: I renamed your loop variables to avoid redefining the original lists. Also, there's no need for pre-calculating points
or list()
ing out the zip(...)
into mylist
. A for loop can iterate over a zip
just fine, and you can convert the score to a float
inside the loop.