Python Overwriting List Element - python

Is there a quick and easy way that is not computationally expensive to overwrite an element in a list corresponding to an element in another list (of the same length)?
iterates = input("How many iterates: ")
trials = input("How many trials: ")
aggregateList = [iterates]
def function():
recordList = []
for i in range(iterates):
# math goes here
recordList.append()
aggregateList[i] += recordList[i]
for i in range(trials):
function()
The problem is coming from aggregateList[i] += recordList[i]Any ideas on something else that will work? Say the value in recordList[i] is 5 for the first "iteration", 5 for the second, 5 for the third, at this time aggregateList[i] should be 15.

I think you are looking for either:
aggregateList += recordList
or
aggregateList.append(recordList)
depending on whether you want your aggregate to be flat or nested.
And change aggregateList = [iterates] to aggregateList = [].
This is how I personally would implement it:
iterates = input("How many iterates: ")
trials = input("How many trials: ")
def function():
recordList = []
for i in range(iterates):
# math goes here
recordList.append()
return recordList
aggregateList = []
for i in range(trials):
aggregateList.append(function())
Or even:
def calculate (i): pass #math goes here
#nested:
aggregateList = [[calculate(i) for i in range(iterates)] for _ in range(trials)]
#flat:
aggregateList = [x for trial in ([calculate(i) for i in range(iterates)] for _ in range(trials)) for x in trial]

Let us assume you've have a list of lists (in a variable name lists). This would be after you have called your 'function()' function (not the greatest function name by the way) and collected your recordLists in a list.
trials = 3
lists = [[1,2,3],[4,5,6],[7,8,9]]
for i in range(trials):
aggregateList = [reduce(lambda x, y: x+y, [listn[i] for listn in lists]) for i in range(trials)]
print aggregateList
would output
[12, 15, 18]
which I think is the type of solution you are looking for.
reduce is a fun function from functional programming. It allows you to apply the anonymous function lambda continuously to items of a list and then return the accumulated value. So in this case, it is preforming (1+4)+7,(2+5)+8,(3+6)+9. The list we are applying reduce to is constructed through a comprehension to extract the i's from the lists inside lists. The call to reduce is wrapped inside another comprehension to return a list of the results.

So iterates is a number like 4, and trials another like 3.
aggregateList = [iterates]
now aggregateList = [4]. What's the purpose of that?
def function():
recordList = []
for i in range(iterates):
# math goes here
recordList.append()
what are you appending to recordList? That last line should produce an error like: append() takes exactly one argument (0 given)
aggregateList[i] += recordList[i]
what is i at this point? The last value of the above iteration, i.e. iterates-1 =3, or is supposed to be the trials iterator. How many items do you expect aggregateList to have at this point? As written I expect it to give an error: IndexError: list assignment index out of range.
for i in range(trials):
function()
What is 'the problem'? What error message or bad result were you getting?
I suspect you are more familiar with another language, and trying to apply its idioms to Python. Also, get the calculation working before worrying about efficiency. At some point, though you might want to use numpy which adds arrays, and the ability to do math on a whole array at once.

Related

Stopping a Python iterator/generator after a given number of times

I have a generator with many elements, say
long_generator = (i**2 for i in range(10**1000))
I would like to extract the first n elements (without obviously parsing the generator until the end): what pythonic way could do this?
The function iter has a second parameter being a sentinel based on the returned value:
numbers = iter(lambda:next(long_generator), 81) # but this assumes we know the results
So would there be an equivalent based on the number of "iterations" instead?
I came up with the following function:
def first_elements(iterable, n:int):
"""Iterates over n elements of an iterable"""
for _ in range(n):
yield next(iterable)
And you could get a list as follows: first_10 = list(first_elements(long_generator, 10))
Is there some built-in or better/more elegant way?

Creating a recursive function to cycle through lists that produce lists that produce lists... and so on

First off I'm using python.
I have a list of items called tier1 it looks like this.
tier1 = ['a1','a2,'a3',..,'an']
I have 2 functions called functionA and functionZ.
They both take a string as their argument and produce a list output like this. The lists must be produced during execution time and are not available from the start. Only tier1 is available.
listOutput = functionA(tier1[0]).
listOutput looks like this
listOutput = ['b1','b2,'b3',..,'bn']
The next time functionA is used on listOutput lets say item 'b1', it will produce
listOutput = functionA('b1')
output:
listOutput = ['bc1','bc2,'bc3',..,'bcn']
This time when functionA is used, on lets say 'bc1', it might come up empty, so functionZ is used on 'bc1' is used instead and the output is stored somewhere.
listOutput = functionA('bc1')
output
listOutput = []
So I use
listOutput = functionZ('bc1')
output
listOutput = ['series1','series2','series3',....,'seriesn']
Now I have to go back and try bc2, until bcn doing the same logic. Once that's done, I will use functionA on 'b2'. and so on.
The depth of each item is variable.
It looks something like this
As long as listOutput is not empty, functionA must be used on the listOutput items or tier1 items until it comes up empty. Then functionZ must be used on whichever item in the list on which functionA comes up empty.
After tier1, listOutput will also always be a list, which must also be cycled through one by one and the same logic must be used.
I am trying to make a recursive function based on this but I'm stuck.
So far I have,
def recursivefunction (idnum): #idnum will be one of the list items from tier1 or the listOutputs produced
listOutput = functionA(idnum)
if not listOutput:
return functionZ(idnum)
else:
return recursivefunction(listOutput)
But my functions return lists, how do I get them to go deeper into each list until functionZ is used and once it's used to move on to the next item in the list.
Do I need to create a new kind of data structure?
I have no idea where to start, should I be looking to create some kind of class with linked lists?
The way I understand your problem:
there is an input list tier1, which is a list of strings
there are two functions, A and Z
A, when applied to a string, returns a list of strings
Z, when applied to a string, returns some value (type is unclear, assume list of string as well)
the algorithm:
for each element of tier1, apply A to the element
if the result is an empty list, apply Z to the element instead, no further processing
otherwise, if the result is not empty, apply the algorithm on the list
So, in Python:
from random import randint
# since you haven't shared what A and Z do,
# I'm just having them do random stuff that matches your description
def function_a(s):
# giving it a 75% chance to be empty
if randint(1, 4) != 1:
return []
else:
# otherwise between 1 and 4 random strings from some selection
return [['a', 'b', 'c'][randint(0, 2)] for _ in range(randint(1,4))]
# in the real case, I'm sure the result depends on `s` but it doesn't matter
def function_z(s):
# otherwise between 0 and 4 random strings from some selection
return [['x', 'y', 'z'][randint(0, 2)] for _ in range(randint(0,4))]
def solution(xs):
# this is really the answer to your question:
rs = []
for x in xs:
# first compute A of x
r = function_a(x)
# if that's the empty list
if not r:
# then we want Z of x instead
r = function_z(x)
else:
# otherwise, it's the same algorithm applied to all of r
r = solution(r)
# whatever the result, append it to rs
rs.append(r)
return rs
tier1 = ['a1', 'a2', 'a3', 'a4']
print(solution(tier1))
Note that function_a and function_z are just functions generating random results with the types of results you specified. You didn't share what the logic of A and Z really is, so it's hard to verify if the results are what you want.
However, the function solution does exactly what you say it should - if I understand you somewhat complicated explanation of it correctly.
Given that the solution to your question is basically this:
def solution(xs):
rs = []
for x in xs:
r = function_a(x)
if not r:
r = function_z(x)
else:
r = solution(r)
rs.append(r)
return rs
Which can even be rewritten to:
def solution_brief(xs):
return [function_z(r) if not r else solution(r) for r in [function_a(x) for x in xs]]
You should reexamine your problem description. The key with programming is understanding the problem and breaking it down to its essential steps. Once you've done that, code is quick to follow. Whether you prefer the first or second solution probable depends on experience and possibly on tiny performance differences.
By the way, any solution written as a recursive function, can also be written purely iterative - that's often preferable from a memory and performance perspective, but recursive functions can have the advantage of being very clean and simple and therefore easier to maintain.
Putting my coding where my mouth is, here's an iterative solution of the same problem, just for fun (not optimal by any means):
def solution_iterative(xs):
if not xs:
return xs
rs = xs.copy()
stack_rs = [rs]
stack_is = [0]
while stack_rs:
r = function_a(stack_rs[-1][stack_is[-1]])
if not r:
stack_rs[-1][stack_is[-1]] = function_z(stack_rs[-1][stack_is[-1]])
stack_is[-1] += 1
else:
stack_rs[-1][stack_is[-1]] = r
stack_rs.append(r)
stack_is.append(0)
while stack_is and stack_is[-1] >= len(stack_rs[-1]):
stack_is.pop()
stack_rs.pop()
if stack_is:
stack_is[-1] += 1
return rs

Using a for loop to calculate the average

Hi I'm sort of new to programming and I would really appreciate some help with this problem.
I have a list of scores and I would like to create a function which divides each individual score by the calculated average of the whole list. The function should accept a list of scores as an argument and return a list with the modified scores.
Also, it should make use of a for loop and a return statement.
Here is a brief example of the list of scores I have:
13
22
33
42
25
(there are over 500 scores)
tbh, the wording of your question was a little confusing, but here's what you would do.
def scoreAvg(scores):
scoresSum = sum(scores)
scoresSum /= len(scores)
newScores = []
for i in scores:
i /= scoresSum
newScores.append(i)
return newScores
print(scoreAvg([13,22,33,42,25]))
You said you were pretty new to python, so I'll give you a rundown of what's happening here. Input 'scores' is a list containing our set of example scores (remember to enclose the input in square brackets). We find the sum of that list with sum() and the length with len(). We then begin a for loop to loop through the elements of scores, and divide each element by the avg, then append that value to a list we created earlier to hold the new scores. Now all we have to do is return that list with return newScores !
Hope I could help.
You can try the following code.
from __future__ import division #For decimal division.
''' Function (func) '''
def func(lst):
new_list = [] #Define an empty new list.
for i in range(len(lst)):
new_list += [ lst[i]*len(lst) / sum(lst) ]
return new_list
mylist = [13, 22, 33, 42, 25] #List you wish to enter.
mod_list = func(lst = mylist) #Modified list.
print mod_list #Prints output (mod_list).
>>>[0.48148148148148145, 0.8148148148148148, 1.2222222222222223, 1.5555555555555556, 0.9259259259259259]
In the above code, each element of new_list is element of input list (lst=mylist) divided by average of input list. One can obtain average by using the following: average = sum of input list / number of elements in input list. In python, the function len() gives you the number of items of an object (e.g. list). The function sum() gives you the sum elements of an object.
I hope this was helpful. Let me know if you have any questions. =)

I'm trying simplify my code but the answer is wrong

This is my code (It's right):
if __name__ == '__main__':
n = int(input())
arr = map(int, input().split())
l = list(set(sorted(arr)))
l.remove(max(l))
print(max(l))
But I want do this (pythonic):
if __name__ == '__main__':
n = int(input())
arr = map(int, input().split())
l = list(set(sorted(arr)))
print(l.remove(max(l)))
So.. when I do this my code just print:
print(l.remove(max(l)))
None
What's the problem? I just want simplify my code.
The task: I've a list and I want print the second maximum score.
Take a look at the documentation. The list.remove method is one that modifies the list in-place. That is to say, it modifies the list that you call it on, instead of returning a new one with the change you want.
Since this function returns nothing, printing l.remove() gives you "None". To print the list with the element removed, you'll have to stick with your original code.
Convert the map object to a set with set(), convert to sorted list with sorted() and take the second last element with [-2]:
print(sorted(set(arr))[-2])
In my opinion, this is more Pythonic than removing the max and then printing the new max as it is clearer and achieved in less steps.
You should use a heap instead of sorting. You can build a heap in O(n) time
and return the kth largest item (for any constant k) in O(n) time as well; sorting takes O(n lg n) time.
import heapq
n = int(input())
arr = [int(x) for x in input.split()]
heapq.heapify(arr) # In-place; does not return the heapified list.
print(heapq.nlargest(2, arr)[-1])

Changing from lists to arguments in Python 3.0

I've recently constructed a piece of python code which finds the least commonly repeated number in a list! Here is my code...
from collections import Counter
def least_common():
from collections import Counter
List = [1,1,1,0,0,3,3,2]
CountList = Counter(List)
Mincount = min(CountList.values())
least_common = next(n for n in reversed(List) if CountList[n] == Mincount)
print (least_common)
least_common()
However as you can clearly see, this uses a list to call the numbers which will be compared.
I'm now trying to get it to do the same task, but instead of using a built in list, I want it to use an argument of integers.
For example
def the_least_common(integers)
--------code with argument which will find lowest repeated number---------
print the_least_common([1,1,1,0,0,3,3,2])
LEAST COMMON BEING 2
Is any of the code which I've already created reusable for what I now need to create? Apologies if this is a stupid question or comes across as really simple as I'm a little stuck
Any advice is much appreciated!
Since you're using Counter, there's a builtin method - most_common - that returns a sorted list of elements and their counts, starting with the most common first. You can query the last element of this list.
In [418]: Counter([1,1,1,0,0,3,3,2]).most_common()[-1]
Out[418]: (2, 1)
Your function would look something like this:
def least_common(data):
return Counter(data).most_common()[-1][0]
If your data can have multiple integers with the same least count, and your function needs to return every one of them, you can iterate over most_common:
def least_common(data):
c = Counter(data).most_common()[::-1]
yield c[0][0]
for x, y in c[1:]:
if x != c[0][1]:
break
yield y

Categories

Resources