john
john

Reputation: 43

loop indentation in python

The function avgavg() takes as input a list whose items are lists of three numbers. Each three-number list represents the three grades a particular student received for a course. For example, here is an input list for a class of four students:

 [[95,92,86], [66,75,54],[89, 72,100],[34,0,0]]

The function avgavg() should print, on the screen, two lines. The first line will contain a list containing every student’s average grade. The second line will contain just one number: the average class grade, defined as the average of all student average grades.

avgavg([[95, 92, 86], [66, 75, 54],[89, 72, 100], [34, 0, 0]])
[91.0, 65.0, 87.0, 11.333333333333334]
63.5833333333

Below is my code, it works perfectely fine if user enter 4 list, but would not work if list is less or greater than 4. Can you please help me with the loop for the second part.

def avg(lst):
    i = 0 
    A = 0 
    C = 0 
    for row in lst :
        for item in row:
            B = (lst[i][A]+lst[i][A+1]+lst[i][A+2])/len(lst[i])
            D = lst[i][A]+lst[i][A+1]+lst[i][A+2] 
        C = C+D
        print (B,end=' ')
        i = i +1
    print ()
    E = len(lst[A])+len(lst[A+1])+len(lst[A+2])+len(lst[A+3])
    C = C/E
    print (C)
    return

Output
In [163]: lst = [[95, 92, 86], [66, 75, 54], [89, 72, 100],[34, 0, 0]]
In [164]: avg(lst)
91.0 65.0 87.0 11.333333333333334 
63.58333333333333

I tried to put the E inside the Loop but i will get out of index with i changing the value.

Upvotes: 3

Views: 386

Answers (7)

Francesco
Francesco

Reputation: 531

Your problem is that your E has 4 elements so, of course, it will work only in the case that you have a list (lst) with exacly four elements.

I don't understand why you have a for each loop and then a index, you can just do a normal loop (for i in range(len(lst)). Here i re-wrote your code adding try - except in order to be sure that the list is not empty. So my idea is to just iterate one type (because I know that every sublist is of len = 3) and print out the average on every iteration and in the same time add it to a variable class_gr (the total grade of the class). Let me know if you need some extra explanations :)

def avg(lst):
   try:
       lst[0]
       class_gr = 0
       for row in lst :
             aver_gr = (row[0] + row[1] + row[2]) /3
             class_gr += aver_gr
             print(aver_gr,end = ' ')
       print('\n'+  str(class_gr/len(lst)))
   except IndexError:
       print('List is empty!')

lst = [[1,2,3],[0,42,9]]
avg(lst)

Output:

2.0 17.0 
9.5

Upvotes: 1

Ahasanul Haque
Ahasanul Haque

Reputation: 11134

Why are you making it that complex?

If I would write it, i might write it like that:

classAverage = sum([sum(i)/len(i) for i in lst])/len(lst)

Now forget about the pythonic way and list comprehension , how about that solution?

def avg(lst):
    classSum=0 
    for row in lst :
        sum=0
        for item in row:
            sum = sum + item
        print sum/len(row),
        classSum = classSum + sum
    print
    print classSum/len(lst) 

Extremely from basic, off course not the best of the solutions. Does it help?

Upvotes: 1

mertyildiran
mertyildiran

Reputation: 6613

Your design have too much mistakes. Don't make it too complicated:

from __future__ import division

def avg(list):
        total_grade = 0
        for student in list:
                student_sum = 0
                for grade in student:
                        student_sum += grade
                print student_sum / 3
                total_grade += student_sum / 3
        print " "
        print total_grade / len(list)

grades = [[95,92,86], [66,75,54],[89, 72,100],[34,0,0]]

avg(grades)

If you need any explanation for a line, let me know in comments.

Upvotes: 1

It's important to be generic about the size of list you pass in to avgavg, so hardcoded indexes like this should not be used. lst[A+1] See my solution:

def avgavg(list_of_students):
  averages = []
  avg_class_grade = 0
  for student_grades in list_of_students:
      avg = sum(student_grades) / 3.0
      averages.append(avg)
      avg_class_grade += avg

  avg_class_grade /= len(list_of_students)

  print(averages)
  print(avg_class_grade)

Upvotes: 1

Quentin Roy
Quentin Roy

Reputation: 7887

def avgavg(grade_list):
    # Creates the list containing the average grade of all students.
    # float() is important or you will only get integers (int / int -> int)
    student_avgs = list(float(sum(grades)) / len(grades) for grades in grade_list)
    # The global avg is the mean of student_avgs.
    global_avg = sum(student_avgs) / len(student_avgs)
    print(student_avgs)
    print(global_avg)

avgavg([[95, 92, 86], [66, 75, 54], [89, 72, 100], [34, 0, 0]])

Upvotes: 1

Klaus D.
Klaus D.

Reputation: 14369

How about this?

def avg(lst):
    return sum(lst)/float(len(lst))

def avgavg(lst):
    courses = [avg(l) for l in lst]
    print(' '.join([str(c) for c in courses]))
    print(avg(courses))

This make use of two things you did not consider in your code: list comprehensions and the sum() builtin function.

Upvotes: 1

SirParselot
SirParselot

Reputation: 2700

Instead of using loops you could instead use sum() and since you know the length of each list you could do

student_grades = [[95,92,86], [66,75,54],[89, 72,100],[34,0,0]] #this is the list you pass into the function
all_avg = []
for i in student_grades:
    all_avg.append(sum(i)/3.0)

print (sum(all_avg)/len(all_avg))

63.5833333333

To answer your question though your problem stems from the line

E = len(lst[A])+len(lst[A+1])+len(lst[A+2])+len(lst[A+3])

You constrained yourself to 4 lists only. You can't have less than 4 because of indexing errors and if you have more than 4 then you will leave a list out

Upvotes: 1

Related Questions