How do I write a function that takes the average of a list of numbers - function

I want to avoid importing different modules as that is mostly what I have found while looking online. I am stuck with this bit of code and I don't really know how to fix it or improve on it. Here's what I've got so far.
def avg(lst):
'''lst is a list that contains lists of numbers; the
function prints, one per line, the average of each list'''
for i[0:-1] in lst:
return (sum(i[0:-1]))//len(i)
Again, I'm quite new and this for loops jargon is quite confusing to me, so if someone could help me get it so the output of, say, a list of grades would be different lines containing the averages. So if for lst I inserted grades = [[95,92,86,87], [66,54], [89,72,100], [33,0,0]], it would have 4 lines that all had the averages of those sublists. I also am to assume in the function that the sublists could have any amount of grades, but I can assume that the lists have non-zero values.
Edit1: # jramirez, could you explain what that is doing differently than mine possible? I don't doubt that it is better or that it will work but I still don't really understand how to recreate this myself... regardless, thank you.

I think this is what you want:
def grade_average(grades):
for grade in grades:
avg = 0
for num in grade:
avg += num
avg = avg / len(grade)
print ("Average for " + str(grade) + " is = " + str(avg))
if __name__ == '__main__':
grades = [[95,92,86,87],[66,54],[89,72,100],[33,0,0]]
grade_average(grades)
Result:
Average for [95, 92, 86, 87] is = 90.0
Average for [66, 54] is = 60.0
Average for [89, 72, 100] is = 87.0
Average for [33, 0, 0] is = 11.0

Problems with your code: the extraneous indexing of i; the use of // to truncate he averate (use round if you want to round it); and the use of return in the loop, so it would stop after the first average. Your docstring says 'print' but you return instead. This is actually a good thing. Functions should not print the result they calculate, as that make the answer inaccessible to further calculation. Here is how I would write this, as a generator function.
def averages(gradelists):
'''Yield average for each gradelist.'''
for glist in gradelists:
yield sum(glist) /len(glist)
print(list(averages(
[[95,92,86,87], [66,54], [89,72,100], [33,0,0]])))
[90.0, 60.0, 87.0, 11.0]
To return a list, change the body of the function to (beginner version)
ret = []
for glist in gradelists:
ret.append(sum(glist) /len(glist))
return ret
or (more advanced, using list comprehension)
return [sum(glist) /len(glist) for glist in gradelists]
However, I really recommend learning about iterators, generators, and generator functions (defined with yield).

Related

Result of user-defined function not displaying on web app

I am trying to define a function that divides Amount of money by Number of days.
So far the user can submit values, but I don't know how to make the result display on my Streamlit web app.
I copied part of my code below.
P.S. I am also a complete beginner in Python.
Thanks for any help
#HOW OFTEN EAT OUT
st.write("2. How often do you eat out?")
form04 = st.form(key='form04')
days = form04.text_input('Please enter average number of days')
submit04 = form04.form_submit_button('Submit')
#HOW MUCH INCOME
if submit04:
st.write('3. What is your monthly income?')
form05 = st.form(key='form05')
income = form05.text_input('Please enter monthly income')
submit05 = form05.form_submit_button('Submit')
if submit05:
def idealbudget(days, income):
budget=float(income)/float(days)
return float(budget)
st.write('Result is', budget)
In this code snippet, you define a function but you never actually call it:
if submit05:
def idealbudget(days, income):
budget=float(income)/float(days)
return float(budget)
st.write('Result is', budget)
Additionally, your st.write call is tabbed incorrectly, it should be at the same level as the def statement. A working solution probably looks like the following (untested):
if submit05:
def idealbudget(days, income):
budget=float(income)/float(days)
return float(budget)
st.write('Result is', idealbudget(days, income))

Use of function / return

I had the task to code the following:
Take a list of integers and returns the value of these numbers added up, but only if they are odd.
Example input: [1,5,3,2]
Output: 9
I did the code below and it worked perfectly.
numbers = [1,5,3,2]
print(numbers)
add_up_the_odds = []
for number in numbers:
if number % 2 == 1:
add_up_the_odds.append(number)
print(add_up_the_odds)
print(sum(add_up_the_odds))
Then I tried to re-code it using function definition / return:
def add_up_the_odds(numbers):
odds = []
for number in range(1,len(numbers)):
if number % 2 == 1:
odds.append(number)
return odds
numbers = [1,5,3,2]
print (sum(odds))
But I couldn’t make it working, anybody can help with that?
Note: I'm going to assume Python 3.x
It looks like you're defining your function, but never calling it.
When the interpreter finishes going through your function definition, the function is now there for you to use - but it never actually executes until you tell it to.
Between the last two lines in your code, you need to call add_up_the_odds() on your numbers array, and assign the result to the odds variable.
i.e. odds = add_up_the_odds(numbers)

Adding the results of multiple functions

Using python 3.3
Stumbled upon another problem with my program. Its the same solar program. Again i decided to add more functionality. Its basically ad-hoc. I'm adding things as i go along. I realize it can be made more efficient but once i decide its done, I'll post the whole coding up.
Anyway, i need to add the results from multiple functions. Here's a part of my coding:
def janCalc():
for a in angle(0,360,10): #angle of orientation
for d in days(1,32,1.0006630137): #day number of year
for smodule in equation(): #equation() function not shown in this coding
total_jan+=smodule #total_jan is already defined elsewhere
avg_jan=total_jan/(60*(1.0006630137*31))
ratio_jan=avg_jan/5.67
calcJan=(ratio_jan*4.79)
yield calcJan
total_jan=0 #necessary to reset total to 0 for next angle interval
def febCalc():
for a in angle(0,360,10):
for d in days ((1.0006630137*31),61,1.0006630137):
for smodule in equation():
total_feb+=smodule
avg_feb=total_feb/(60*(1.0006630137*28))
ratio_feb=avg_feb/6.56
calcFeb=(ratio_feb*4.96)
yield calcFeb
total_feb=0
#etc..............
Is there anyway to add the yield of each function?
for e.g: calcJan+calcFeb+.....
I would like to get the total results under each angle interval and then dividing by 12 to get the average value per interval. Like so:-
0 degrees---->total/12
10 deg ---->total/12
20 deg ---->total/12
30 deg ---->total/12
........
360 deg ---->total/12
If you need more info, let me know.
ADDENDUM
The solution was essentially solved by #jonrsharpe. But i encountered a bit of a problem.
Traceback (most recent call last):
File "C:\Users\User\Documents\Python\Solar program final.py", line 247, in <module>
output=[sum(vals)/12 for vals in zip(*(gen() for gen in months))]
File "C:\Users\User\Documents\Python\Solar program final.py", line 247, in <listcomp>
output=[sum(vals)/12 for vals in zip(*(gen() for gen in months))]
File "C:\Users\User\Documents\Python\Solar program final.py", line 103, in janCalc
for smodule in equation():
File "C:\Users\User\Documents\Python\Solar program final.py", line 63, in equation
d=math.asin(math.sin(math.radians(23.45))*math.sin(math.radians((360/365.242)*(d-81))))
NameError: global name 'd' is not defined
I've isolated it to:
for d in days ((1.0006630137*31),61,1.0006630137):
for smodule in equation():
It turns out i can't reference a function from inside a function? I'm not too sure. So even my original coding did not work. I assumed it was working because previously i had not defined each month as a function. I should have tested it out first.
Do you know how to get around this?
A simple example to demonstrate how to combine multiple generators:
>>> def gen1():
for x in range(5):
yield x
>>> def gen2():
for x in range(5, 10):
yield x
>>> [sum(vals) for vals in zip(*(gen() for gen in (gen1, gen2)))]
[5, 7, 9, 11, 13]
Or, written out long hand:
output = list(gen1())
for index, value in enumerate(gen2()):
output[index] += value
You can modify either version to include a division, too, so your case would look something like:
months = [janCalc, fabCalc, ...]
output = [sum(vals) / 12 for vals i zip(*(gen() for gen in months))]

Ruby on Rails optimalization of some code

I have some simple code that uses the minmax algoritm to locate birds. Everything works but I find my programming not good and I believe there is a better solution. I'm not that experienced in RoR but if somebody knows a better way to achieve the same solution then I'm greatful ;).
There are two parts I hate, the 4 lists I had to create to determine the max or min value for the different combinations (the core of the min-max algorithm) and the very ugly SQL hack.
Thanks!
def index
# fetch all our birds
#birds = Bird.all
# Loop over the birds
#birds.each do |bird|
#fixed = Node.where("d7type = 'f'")
xminmax = []
xmaxmin = []
yminmax = []
ymaxmin = []
#fixed.each do |fixed|
rss = Log.find_by_sql("SELECT logs.fixed_mac, AVG(logs.blinker_rss) AS avg_rss FROM logs
WHERE logs.blinker_mac = '#{bird.d7_mac}' AND logs.fixed_mac = '#{fixed.d7_mac}' ORDER BY logs.id DESC LIMIT 30")
converted_rss = calculate_distance_rss(rss[0].attributes["avg_rss"])
xminmax.push(fixed.xpos + converted_rss)
xmaxmin.push(fixed.xpos - converted_rss)
yminmax.push(fixed.ypos + converted_rss)
ymaxmin.push(fixed.ypos - converted_rss)
end
pos = {x: (xminmax.min + xmaxmin.max) / 2, y: (yminmax.min + ymaxmin.max) / 2}
puts pos
end
end
2 things you could do to start with is (assuming Birds could be a large table) Change Bird.all to
Bird.find_each do |bird|
... code ...
end
It's a more efficient way to loop over many table records.
2nd: take #fixed = Node.where("d7type = 'f'") out of the each loop since it doesn't need any variables for its query. Put it above the loop so it doesn't execute each time.
3rd (Not so much of an optimization but just safer code): Your Log.find_by_sql looks simple enough to use active_record, you can change it to:
Log.select('fixed_mac, AVG(logs.blinker_rss) AS avg_rss, blinker_mac').
where(blinker_mac: bird.d7_mac, fixed_mac: fixed.d7_mac).
order('id DESC').limit(30)
converted_rss = calculate_distance_rss(rss.first.avg_rss)
Everything else looks fine.

Why does my use of Perl's split function not split?

I'm trying to split an HTML document into its head and body:
my #contentsArray = split( /<\/head>/is, $fileContents, 1);
if( scalar #contentsArray == 2 ){
$bodyContents = $dbh->quote(trim($contentsArray[1]));
$headContents = $dbh->quote(trim($contentsArray[0]) . "</head>");
}
is what i have. $fileContents contains the HTML code. When I run this, it doesn't split. Any one know why?
The third parameter to split is how many results to produce, so if you want to apply the expression only once, you would pass 2.
Note that this does actually limit the number of times the pattern is used to split the string (to one fewer than the number passed), not just limit the number of results returned, so this:
print join ":", split /,/, "a,b,c", 2;
outputs:
a:b,c
not:
a:b
sorry, figured it out. Thought the 1 was how many times it would find the expression not limit the results. Changed to 2 and works.