Python- Function which returns the average mark - python

I am trying to create a function which returns the average of a student's module. The student's data is stored in a list which contains the following, so Dave has: ('Dave', 0, 'none', 'M106', ['50'])
and then Ollie has: ('Ollie', 'M104', 0, 'none', ['60']). I can't get my head around how to get the average from the two averages.
def moduleAverage(self):
if student.getAverage is > 0:
return self.moduleAverage

Ok first I have to say: Correct your indentation.
So I'll make a little example now:
studentDetails = []
studentDetails.append(('Peter', ['40']))
studentDetails.append(('Frank', ['100']))
studentDetails.append(('Ernest', ['40']))
def moduleAverage(inList):
total = 0.0
for i in xrange(0, len(inList)):
total += float(inList[i][1][0]) # the score is at the index 1 in the tuple (('Peter', ['40']))
return (total / float(len(inList)))
print moduleAverage(studentDetails)
Pay attention: You have the single mark ['40'] as a string, so you have to convert it to float.
Also remain the same order in the student tuple.
I don't know your whole structure so I just made a simple example of the algorithm with tuples as you mentioned in your question.

Related

How do I print lists side by side in Python?

New user practicing lists and loops. My goal is create two list from my own input (range is 2 for quick testing, but want to get to 10). I have hit a wall on two problems:
I would like my lists to sit side by side ie.
First Name \t\t\t $77
Next Name \t\t\t $16
I don't know how to change my types so that int or float is not iterable error does not persists. I believe it'll help with my coded out max/min statements
My code:
list1 = []
list2 = []
count = 0
for i in range(2):
customers = input("Customers name? ")
list1.append(customers)
spent = float(input("Amount spent? "))
list2.append(spent)
count += spent
averageSpent = count / 2 # change this when changing range
print("Name\t\t\tAmount")
# won't print side by side. how to use zip()?
print((*list1 + list2), sep = "\n")
print("Total spending:\t\t $", count)
print("Average spending:\t $", averageSpent)
# keep getting 'object is not iterable'
#print("Most money spent:\t $", max(spent))
#print("Least money spent:\t $", min(spent))
My output is currently:
Customers name? work
Amount spent? 45
Customers name? please
Amount spent? 65
Name Amount
work
please
45.0
65.0
Total spending: $ 110.0
Average spending: $ 55.0
Thank you!
Regarding the first issue that you have, the best way for you to print the output side by side would be to iterate over the list and print each value in the list. In addition to that, you can use f-strings which is a feature that we added with python 3.6 and it allows you to do stuff like this:
x = 10
print(f'{x+20}')
>> 30
you can read more about f-strings here.
Regarding the second issue that you're facing. You got this error because you were calling the max() function on a single float. the max function should be called for a list.
I've made some adjustments. Here is what the final code looks like:
list1 , list2 = [] , []
max_range = 2
count = 0
for i in range(max_range):
customer_name = input("Customer name: ")
list1.append(customer_name)
spent = float(input("Amount Spent: "))
list2.append(spent)
count += spent
averageSpent = count / max_range
print("Name\t\t\tAmount")
for i in range(len(list1)):
print(f'{list1[i]} \t\t\t$ {list2[i]}')
print("Total spending:\t\t $", count)
print("Average spending:\t $", averageSpent)
print("Most money spent:\t $", max(list2))
print("Least money spent:\t $", min(list2))
Edit: using the zip function might be another option for printing the two outputs side by side using tuples. However, since you've already said that you're new to these topics I think that you should stay away from zip (for the time being) until you feel comfortable with lists.
Printing things side by side is answered here: Print 2 lists side by side
The error about a float or int not being iterable is because you are calling max(spent) instead of max(list2). The function max() expects a list or other iterable object.
bikemule is correct about the iterables. You need to call max with a list, not a single number. (What would max(101) return? It doesn't quite make sense.)
To make the two lists appear side-by-side, you can use zip combined with a for loop. It will turn the lists into sets of tuples that then will appear in an almost-tabular format when printed.
list_a = [1, 2, 3]
list_b = [4, 5, 6]
for col_a, col_b in zip(list_a, list_b):
print("A_Item: %s | B_Item: %d" %(col_a, col_b))
Returns:
A_Item: 1 | B_Item: 4
A_Item: 2 | B_Item: 5
A_Item: 3 | B_Item: 6

Better time complexity for following task

I was solving following problem today (unfortunately I didnt achieve required better time complexity).
Given a list of student test scores, find the best average grade. Each student may have more than one test score in the list, and the best average grade is the average of all test scores for that student.
Complete the bestAverageGrade function in the editor below.
It has one parameter, scores, which is an array of student test scores. Each element in the array is a two-element array of the form [student name, test score] e.g. [ "Bobby", "87"].
More points will be awarded for solutions that can handle larger inputs within a set period of time i.e. code with a faster run-time complexity.
Input Format
The input parameter scores is an array of arrays, where each sub-array contains two strings: the student name followed by a test score as a string. You must also include the number of entries and the size of each entry (this will always be 2). See below for specific examples. Test scores may be positive or negative integers.
Output Format
Your function must return a single integer representing the best average grade. If you end up with an average grade that is not an integer, you should use a floor function to return the largest integer less than or equal to the average.
Return 0 for an empty input.
Sample Input 0
[ [ "Bobby", "87" ],
[ "Charles", "100" ],
[ "Eric", "64" ],
[ "Charles", "22" ] ]
entered as
4
2
Bobby 87
Charles 100
Eric 64
Charles 22
Sample Output 0
87
and here is me bestAverageGrade method:
def bestAverageGrade(scores):
list_of_students = set([x[0] for x in scores])
averages = []
for student in list_of_students:
results = [float(x[1]) for x in scores if x[0] == student]
averages.append(sum(results_of_student)/len(results))
return math.floor(max(averages))
How could I achieve better time complexity? I know that now list of lists is iterated two times.
You iterate over the list several times: one time for each student. If there are multiple students, then the number of loops can be rather large, so the time complexity can be - worst case - O(n2).
We can use an approach where we for instance using a dictionary. We can define a dictionary grades that maps every student name on a 2-tuple (a numerator and denominator). In that case the code looks like:
Vanilla Python
def bestAverageGrade(scores):
grades = {}
for student, grade in scores:
grade = float(grade)
current = grades.get(student)
if current is None:
grades[student] = grade, 1
else:
num, denom = current
grades[student] = num + grade, denom + 1
return math.floor(max(num/denom for num, denom in grades.values()))
Pandas
We can also boost performance by using Pandas. For example:
import pandas as pd
def bestAverageGrade(scores):
df = pd.DataFrame([[name, float(score)] for name, score in scores],
columns=['student', 'score'])
return math.floor(df.groupby('student')['score'].mean().max())
So here we first group by students and take the mean as aggregate for the 'score' column. Then we take the maximum over all these students.
Using Javascript.
function bestAverageGrade(scores) {
if(!Array.isArray(scores) || scores.length === 0) return 0;
let duplicateFrequency = {};
let sumFrequency = {};
scores.forEach(item => {
duplicateFrequency[item[0]] = duplicateFrequency[item[0]] ? duplicateFrequency[item[0]]+1 : 1;
sumFrequency[item[0]] = sumFrequency[item[0]] ? sumFrequency[item[0]]+Number(item[1]) : Number(item[1]);
})
for( let props in duplicateFrequency) {
sumFrequency[props] = Math.floor(sumFrequency[props] / duplicateFrequency[props])
}
return Math.max(...Object.values(sumFrequency))
}
Time Complexity here is O(n)
Approach: Here we are using two hashMaps one for storing the duplicates the other for storing the total marks for each student.
Then we are just reflecting over one of the hashMaps and dividing the total sum with the duplicates. Flooring the result to avoid decimals.
Finally, just use Math.max to get the maximum value.

Function problems

So I have two lists:
typeList — list of strings of transaction types (addition, subtraction)
valueList — List of values either added or subtracted.
as both value and type are appended to the list at the same index, I need to make a function to calculate the sum of the total value added and the total value subtracted, but I've been really stuck on it for ages trying to get my head around just how to do it.
desiredType is just the type of transaction that is being looked for. As you'll see, I called my function twice with each type.
I understand that the index values need to be obtained and used between the two lists but not sure how to sum the values up.
def showInfo(typeList, valueList, desiredType):
for i in range(len(valueList)):
if typeList[i] == desiredType:
total = total + valueList[i]
return (total)
Call to the function:
if choice == "I": #Prints transaction information
print (showInfo(transactionTypes,transactionAmounts, "Addition"))
print (showInfo(transactionTypes,transactionAmounts, "Subtraction"))
Any help would be appreciated as well as an explanation on how it's done.
You can zip together those 2 lists, then you don't have to keep track of the index you're looking at:
def transaction_total(types, amounts, desired_type):
total = 0
for transaction_type, amount in zip(types, amounts):
if transaction_type == desired_type:
total += amount
return total
However, you're really just filtering values and summing them. Python makes this cleaner using generator expressions and the sum function:
def transaction_total(types, amounts, desired_type):
return sum(amount for transaction_type, amount in zip(types, amounts)
if transaction_type == desired_type)
If you need to keep your data unmodified, you can just make your function more efficient (just one call) :
def showInfo(typeList, valueList):
for i in range(len(valueList)):
if typeList[i] == "Addition":
total_add = total_add + valueList[i]
else:
total_sub = total_sub - valueList[i]
return (total_add, total_sub)

Comparing list items and tuples

In Python 3, I'm trying to create a program which takes input from a user as 3 digit codes and converts them into items in a list. It then compares these items with the first(the 3 digit code) part of a tuple in a list of tuples and prints the whole tuple.
import shares
portfolio_str=input("Please list portfolio: ")
portfolio_str= portfolio_str.replace(' ','')
portfolio_str= portfolio_str.upper()
portfolio_list= portfolio_str.split(',')
print(portfolio_list)
print()
print('{:<6} {:<20} {:>8}'.format('Code', 'Name', 'Price'))
data=shares.EXCHANGE_DATA
for (code, name, share_value) in data:
if code == i in portfolio_list:
print('{:<6} {:<20} {:>8.2f}'.format(code, name, share_value))
else:
print("Failure")
As you can see I'm using a module called shares containing a list of tuples called EXCHANGE_DATA which is set out like this:
EXCHANGE_DATA = [('AIA', 'Auckair', 1.50),
('AIR', 'Airnz', 5.60),
('AMP', 'Amp',3.22),
('ANZ', 'Anzbankgrp', 26.25),
('ARG', 'Argosy', 12.22),
('CEN', 'Contact', 11.22),
('CNU', 'Chorus',3.01),
('DIL', 'Diligent', 5.3),
('DNZ', 'Dnz Property', 2.33),
('EBO', 'Ebos', 1.1),
An exemplar input would be:
AIA, AMP, ANZ
The corresponding output would be:
Code Name Price
AIA Auckair 1.50
AMP Amp 3.22
ANZ Anzbankgrp 26.25
I'm just stuck on the for and/or if statements which I think I need.
Your issue is this here:
if code == i in portfolio_list:
This doesn't make sense in Python. in checks if a given value is contained in the list, so this checks if i is in portfolio_list, then checks if code is equal to True or False (whatever i in portfolio_list returned. What you want is simply:
if code in portfolio_list:
Note that if portfolio_list could be long, it might be worth making it a set, as checking for membership in a set is significantly more efficient for large amounts of data.
Your syntax appears to be a mashup of different methodologies. You might have meant:
if any(code == i for i in portfolio_list):
However, as this is directly equivalent to code in portfolio_list, but more verbose and inefficient, it's not a good solution.

Python Min-Max Function - List as argument to return min and max element

Question: write a program which first defines functions minFromList(list) and maxFromList(list). Program should initialize an empty list and then prompt user for an integer and keep prompting for integers, adding each integer to the list, until the user enters a single period character. Program should than call minFromList and maxFromList with the list of integers as an argument and print the results returned by the function calls.
I can't figure out how to get the min and max returned from each function separately. And now I've added extra code so I'm totally lost. Anything helps! Thanks!
What I have so far:
def minFromList(list)
texts = []
while (text != -1):
texts.append(text)
high = max(texts)
return texts
def maxFromList(list)
texts []
while (text != -1):
texts.append(text)
low = min(texts)
return texts
text = raw_input("Enter an integer (period to end): ")
list = []
while text != '.':
textInt = int(text)
list.append(textInt)
text = raw_input("Enter an integer (period to end): ")
print "The lowest number entered was: " , minFromList(list)
print "The highest number entered was: " , maxFromList(list)
I think the part of the assignment that might have confused you was about initializing an empty list and where to do it. Your main body that collects data is good and does what it should. But you ended up doing too much with your max and min functions. Again a misleading part was that assignment is that it suggested you write a custom routine for these functions even though max() and min() exist in python and return exactly what you need.
Its another story if you are required to write your own max and min, and are not permitted to use the built in functions. At that point you would need to loop over each value in the list and track the biggest or smallest. Then return the final value.
Without directly giving you too much of the specific answer, here are some individual examples of the parts you may need...
# looping over the items in a list
value = 1
for item in aList:
if item == value:
print "value is 1!"
# basic function with arguments and a return value
def aFunc(start):
end = start + 1
return end
print aFunc(1)
# result: 2
# some useful comparison operators
print 1 > 2 # False
print 2 > 1 # True
That should hopefully be enough general information for you to piece together your custom min and max functions. While there are some more advanced and efficient ways to do min and max, I think to start out, a simple for loop over the list would be easiest.

Categories

Resources