0

This is one list

[74.0, 96.0, 72.0, 88.0, ['71', '80', '83', '77', '90', '88', '95', '71', '76', '94'], 80.0, 74.0, 98.0, 77.0]

74 is calculated with the weight .1, 96 with the weight .1, 72 with the weight .15, 88 with the weight .05, the average of (71,80,83,77,90,88,95,71,76,94) calculated with the weight .3, 80 calculated with the weight .08, 74 with the weight .08, 98 with .09 and lastly 77 with .05. Each score should be multiplied by appropriate weight.

Here is the function

def weighted_total_score(student_scores):
    return((int(student_scores[0])*.1)+(int(student_scores[1])*.1)+(int(student_scores[2])*.15)+(int(student_scores[3])*.05)+(int(student_scores[4][0])*.3)+(int(student_scores[5])*.08)+(int(student_scores[5])*.08)+(int(student_scores[5])*.09)+(int(student_scores[8])*.05))

The expected value should be 82.94 but i am getting 78.48

Rachel
  • 43
  • 1
  • 8

1 Answers1

2

You are slicing the outer list:

student_scores[4:5][0]

Slicing produces a new list, in this case with one element, an the [0] selects that nested list:

>>> student_scores = [74.0, 96.0, 72.0, 88.0, ['71', '80', '83', '77', '90', '88', '95', '71', '76', '94'], 80.0, 74.0, 98.0, 77.0]
>>> student_scores[4:5]
[['71', '80', '83', '77', '90', '88', '95', '71', '76', '94']]
>>> student_scores[4:5][0]
['71', '80', '83', '77', '90', '88', '95', '71', '76', '94']

Perhaps you want to use student_scores[4][0] (no slicing, just the 4th element) instead? That'd produce '71':

>>> student_scores[4][0]
'71'

You are also skipping student_scores[5], and will get an IndexError for student_scores[9], which doesn't exist.

You probably want to avoid typing all those direct references; specify your weights as a sequence and use zip() with a generator expression and sum() to calculate the weighted sum:

def weighted_total_score(student_scores):
    weights = .1, .1, .15, .05, .3, .08, .08, .09, .05                 
    return sum(int(s[0] if isinstance(s, list) else s) * w
               for s, w in zip(student_scores, weights))

This uses isinstance(s, list) to detect the one list object and extract the first value from that.

If you need the average of the the nested list, calculate that on the spot:

def average(string_scores):
    return sum(map(int, string_scores), 0.0) / len(string_scores)

def weighted_total_score(student_scores):
    weights = .1, .1, .15, .05, .3, .08, .08, .09, .05                 
    return sum(int(average(s[0]) if isinstance(s, list) else s) * w
               for s, w in zip(student_scores, weights))

The average() function here converts each string in the list to an integer, then sums those integers and divides the result by the length of the list. The sum() is started with a floating point 0.0 to force the total to be a float, this makes sure the division is also producing a float, this only matters on Python 2.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • Thank you ! I will try this. I wasn't sure how to index the list within the list, which consisted of 10 values that needed to be averaged together. – Rachel May 25 '16 at 00:46
  • @RachelSwamy: right, so `sum(map(int, nested_list)) / len(nested_list)`? – Martijn Pieters May 25 '16 at 00:47
  • @RachelSwamy: also, is this Python 2 or 3? Should the average be converted to an integer too? – Martijn Pieters May 25 '16 at 00:48
  • I just tried the code above using the zip and it is giving me 58.39 as an output. I am expecting to receive 81.94. Where did i go wrong here. By the way i am using python 3.5 @MartijnPieters – Rachel May 25 '16 at 01:22
  • @RachelSwamy: how should I know where this goes wrong? You didn't specify anything about the expected output or how it is to be calculated. The output is correct for the weights and the assumption that all floats must be converted to `int()` before multiplying with the weight. – Martijn Pieters May 25 '16 at 01:41
  • @RachelSwamy: it would help if you explained how the value of 81.94 is calculated. Add this to your question. – Martijn Pieters May 25 '16 at 01:41
  • Sorry if i was not specific. The first number in the list should go with the .1, second with .1, third with .15, fourth with .05, avg. of the ten numbers with .3. etc. – Rachel May 25 '16 at 01:44
  • @RachelSwamy: again, edit the question. Show us the sum perhaps. You haven't told us anything about what your function was supposed to do. All I could do was explain why you got the error you got, and I went an extra step by showing you an alternative way to calculate the numbers. It appears that *apart from the error* you asked the question about, your approach has other problems, but you didn't give us any details that would enable us to help you. – Martijn Pieters May 25 '16 at 01:46
  • @RachelSwamy: the better approach is to post a **new** question to help you fix your next problem. The issues as to why you got your error is now resolved. – Martijn Pieters May 25 '16 at 01:46
  • I have just edited my question to provide information on how the weighted score should be calculated as well as what i would like the function to do. Sorry about the confusion @Martijn Pieters – Rachel May 25 '16 at 01:55
  • @RachelSwamy: how does that help calculate the weighted score? That's a decision tree as to what should happen with the result, not how to calculate it. – Martijn Pieters May 25 '16 at 01:56