Reputation: 123
I have the following code in one of my views. The problem is I can't figure out how to refactor it into just one for loop. The only difference is the 'item.' part. I need all three variable values in the same template so I don't think I can pass information from the urls.py. Any ideas of how I can rewrite this so I am not repeating myself?
Thanks.
def average(request):
cal_list = []
cal_list2 = []
cal_list3 = []
exams = Test.objects.filter(test__test_name__iexact="one")
for item in exams:
cal_list.append(int(item.start))
result = sum(cal_list) / float(165) * 100
result = result / len(cal_list)
result = int(round(result))
result = str(result) + '%'
for item in exams:
cal_list2.append(int(item.s1))
result2 = sum(cal_list2) / float(165) * 100
result2 = result2 / len(cal_list2)
result2 = int(round(result2))
result2 = str(result2) + '%'
for item in exams:
cal_list3.append(int(item.s2))
result3 = sum(cal_list3) / float(165) * 100
result3 = result3 / len(cal_list3)
result3 = int(round(result3))
result3 = str(result3) + '%'
return direct_to_template(request, 'a.html', {'result': result, 'result2': result2, 'result3': result3})
Upvotes: 0
Views: 100
Reputation: 24324
you can use the aggregate
to perform the sum at the database layer.
from django.db import models
def average(request):
queryset = Test.objects.filter(test__test_name__iexact="one")
total = queryset.count()
results = queryset.aggregate(
result1=models.Sum('start'),
result2=models.Sum('s1'),
result3=models.Sum('s2'))
def transform(resultsum):
result = resultsum / float(165) * 100
result = result / total
result = int(round(result))
result = str(result) + '%'
return result
result1 = transform(results['result1'])
result2 = transform(results['result2'])
result3 = transform(results['result3'])
return direct_to_template(request, 'a.html', {'result': result1, 'result2': result2, 'result3': result3})
Upvotes: 0
Reputation: 17639
I would just create a function:
def calculate_result(items):
items = tuple(int(i) for i in items)
result = sum(items) / 16500.0
result = result / len(items)
return '%i' % round(result) + '%'
result0 = calculate_result(item.start for item in exams)
result1 = calculate_result(item.s1 for item in exams)
result2 = calculate_result(item.s2 for item in exams)
Upvotes: 1
Reputation: 174622
In your loop you keep overwriting the results
value, so you can extrapolate that part:
for item in items:
cal_list.append(int(item.start))
cal_list2.append(int(item.s1))
cal_list3.append(int(item.s2))
result = "%s%%" % round((sum(cal_list) / float(165) * 100) / len(cal_list))
result2 = "%s%%" % round((sum(cal_list2) / float(165) * 100) / len(cal_list2))
result3 = "%s%%" % round((sum(cal_list3) / float(165) * 100) / len(cal_list3))
Upvotes: 1
Reputation: 56881
There you go for the simplest refactoring, which saved the loop from iterating only on required things and moving the calculation out of the loop.
def average(request):
cal_list = []
cal_list2 = []
cal_list3 = []
exams = Test.objects.filter(test__test_name__iexact="one")
for item in exams:
cal_list.append(int(item.start))
cal_list2.append(int(item.s1))
cal_list3.append(int(item.s2))
result = sum(cal_list) / float(165) * 100
result = result / len(cal_list)
result = int(round(result))
result = str(result) + '%'
result2 = sum(cal_list2) / float(165) * 100
result2 = result2 / len(cal_list2)
result2 = int(round(result2))
result2 = str(result2) + '%'
result3 = sum(cal_list3) / float(165) * 100
result3 = result3 / len(cal_list3)
result3 = int(round(result3))
result3 = str(result3) + '%'
return direct_to_template(request, 'a.html', {'result': result, 'result2': result2, 'result3': result3})
Upvotes: 0