Function problems - python

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)

Related

How to match input with elements in list/dictionary in Python3

I'm very new at coding, and I'm trying to create a shop list with items and prices on it.
That is, once typed in all the items, the function should calculate the sum and stop the moment you exceed the budget.
So I wrote something like:
def shoplist():
list={"apple":30, "orange":20, "milk":60......}
buy=str(input("What do you want to purchase?")
If buy in list:
While sum<=budget:
sum=sum+??
shoplist ()
I really don't know how to match the input of an item with the price in the list...
My first thought is to use 'if', but it's kinda impractical when you have more than 10 items on the list and random inputs.
I'm in desperate need of help....So any suggestions would be nice!! (or if you have a better solution and think me writing it this way is complete garbage... PLEASE let me know what those better solutions are😭😭😭
The code you post will not run in python. list is a builtin and should not be used for a variable name, and is doubly confusing since it refers to a dict object here. input() already returns a str so the cast has no effect. if and while should be lowercase, and there is no indentation, so we have no way of knowing the limits of those statements.
There are so many things wrong, take a look at this:
def shoplist(budget):
prices = {"apple":30, "orange":20, "milk":60}
# Initialise sum
sum = 0
while sum <= budget:
buy = input("What do you want to purchase?")
# Break out of the loop if the user hts <RETURN>
if not buy: break
if buy in prices:
sum += prices[buy] # This gets the price
else:
print("Invalid item", buy)
shoplist(142)
So what have I changed? The budget has to come from somewhere, so I pass it in as a parameter (142, I made that up). I initialise the sum to zero, and I moved the while loop to the outside.
Notice as well lots of whitespace - it makes the code easier to read and has no effect on performance.
Lots of improvements to make. The user should be shown a list of possible items and prices and also how much budget there is left for each purchase. Note as well that it is possible to go over budget since we might only have 30 in the budget but we can still buy milk (which is 60) - we need another check (if statement) in there!
I'll leave the improvements to you. Have fun!
Take a look at this as an example:
# this is a dictionary not a list
# be careful not using python reserved names as variable names
groceries = {
"apple":30,
"orange":20,
"milk":60
}
expenses = 0
budget = 100
cart = []
# while statements, as well as if statements are in lower letter
while expenses < budget:
# input always returns str, no need to cast
user_input = input("What do you want to purchase?")
if user_input not in groceries.keys():
print(f'{user_input} is not available!')
continue
if groceries[user_input] > budget - expenses:
print('You do not have enough budget to buy this')
user_input = input("Are you done shopping?Type 'y' if you are.")
if user_input == 'y':
break
continue
cart.append(user_input)
# this is how you add a number to anotherone
expenses += groceries[user_input]
print("Shopping cart full. You bought {} items and have {} left in your budget.".format(len(cart), budget-expenses))
I've made some changes to your code to make it work, with explanation including using comments indicated by the # symbol.
The two most important things are that all parentheses need to be closed:
fun((x, y) # broken
fun((x, y)) # not broken
and keywords in Python are all lowercase:
if, while, for, not # will work
If, While, For, Not # won't work
You might be confused by True and False, which probably should be lowercase. They've been that way so long that it's too late to change them now.
budget = 100 # You need to initialize variables before using them.
def shoplist():
prices = { # I re-named the price list from list to prices
'apple' : 30, # because list is a reserved keyword. You should only
'orange' : 20, # use the list keyword to initialize list objects.
'milk' : 60, # This type of object is called a dictionary.
} # The dots .... would have caused an error.
# In most programming languages, you need to close all braces ().
# I've renamed buy to item to make it clearer what that variable represents.
item = input('What do you want to purchase? ')
# Also, you don't need to cast the value of input to str;
# it's already a str.
if item in prices:
# If you need an int, you do have to cast from string to int.
count = int(input('How many? '))
cost = count*prices[item] # Access dictionary items using [].
if cost > budget:
print('You can\'t afford that many!')
else:
# You can put data into strings using the % symbol like so:
print('That\'ll be %i.' % cost) # Here %i indicates an int.
else:
print('We don\'t have %s in stock.' % item) # Here %s means str.
shoplist()
A lot of beginners post broken code on StackOverflow without saying that they're getting errors or what those errors are. It's always helpful to post the error messages. Let me know if you have more questions.

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.

Add up the value of data[x] to data[x+1]

I have a long list of data which I am working with now,containing a list of 'timestamp' versus 'quantity'. However, the timestamp in the list is not all in order (for example,timestamp[x] can be 140056 while timestamp[x+1] can be 560). I am not going to arrange them, but to add up the value of timestamp[x] to timestamp[x+1] when this happens.
ps:The arrangement of quantity needs to be in the same order as in the list when plotting.
I have been working with this using the following code, which timestamp is the name of the list which contain all the timestamp values:
for t in timestamp:
previous = timestamp[t-1]
increment = 0
if previous > timestamp[t]:
increment = previous
t += increment
delta = datetime.timedelta(0, (t - startTimeStamp) / 1000);
timeAtT = fileStartDate + (delta + startTime)
print("time at t=" + str(t) + " is: " + str(timeAtT));
previous = t
However it comes out with TypeError: list indices must be integers, not tuples. May I know how to solve this, or any other ways of doing this task? Thanks!
The problem is that you're treating t as if it is an index of the list. In your case, t holds the actual values of the list, so constructions like timestamp[t] are not valid. You either want:
for t in range(len(timestamp)):
Or if you want both an index and the value:
for (t, value) in enumerate(timestamp):
When you for the in timestamp you are making t take on the value of each item in timestamp. But then you try to use t as an index to make previous. To do this, try:
for i, t, in enumerate(timestamp):
previous = timestamp[i]
current = t
Also when you get TypeErrors like this make sure you try printing out the intermediate steps, so you can see exactly what is going wrong.

Python- Function which returns the average mark

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.

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