Python: nested list iteration - python

My list is a nested list like this:
[[3, 0, 5, 2, 2, 3, 5, 1, 3, 4, 2, 3, 5, 4], etc.
function overunder returns tuple like this: (1,2,3,4,5,6)
worksheet2.write writes results in excel file
I need every function result (tuple) to be written on the new row in excel file
So I came up with the following code
for item in list:
ou = overunder(item)
i = 0
ii = []
s = sum(ii)
while i < len(ou):
worksheet2.write(s + 2, i + 2, ou[i])
i += 1
ii.append(1)
It seems working fine, the only problem I have to increment s with each for loop.
But strangely enough ii doesn't get appended.
What may be wrong?

Your problem is that s and ii get their values re-initialized on each for loop. You want to move ii = [] to be defined before the loop. But anyway, that is a weird way of maintaining s with summing the ii list. Your code could be simplified by using the enumerate function:
for row, item in enumerate(lst):
ou = overunder(item)
for col, element in enumerate(ou):
worksheet2.write(row + 2, col + 2, element)
By the way, you didn't mention what library you are using to write to the excel. Using openpyxl you can take advantage of the append method to write a whole line at once and greatly simplify your code:
for item in lst:
worksheet2.append(('', '') + overunder(item))

Okay, try this:
for i in range(6):
print(i)
This will print numbers from zero to five.
I can't understand your problem, but you are initializing your list with ii = [ ], this will delete the contents of your list. After this you sum([ ])
Hope it is helpful!

Related

I am trying to make a function that takes in a list and gives out an edited list in python

I'm trying to make a function, called delta in this case, that will take in an in_list and return and out_list. These are the requirements for the out_list:
len(out_list) == len(in_list)-1
out_list(i) = in_list(i+1)-in_list(i)
I wish to use the function on the lists "times" and "positions" in the code below:
positionfile = open.("positionmeasurements.txt", "r", encoding="utf-8-sig")
filetext = positionfile.read().splitlines()
times = []
positions = []
for i in filetext:
time, position = i.split(";")
times.append(time)
positions.append(position)
This is the code I've got so so far for the function:
def delta(in_list):
for i in in_list:
out_list = in_list[i+1] - in_list[i]
return out_list
The following numbers are the times (left side of the semicolon) and the positions:
0.05;0.9893835
0.1;0.9921275
0.15;0.989212
0.2;0.98784
0.25;0.9876685
0.3;0.988526
0.35;0.991613
0.4;0.9921275
0.45;0.9921275
0.5;0.9886975
0.55;0.985096
0.6;0.983724
0.65;0.9578275
0.7;0.9163245
0.75;0.8590435
0.8;0.7890715
0.85;0.714812
0.9;0.642096
0.95;0.559776
1;0.4776275
1.05;0.398566
1.1;0.315903
1.15;0.2320395
1.2;0.1799035
1.25;0.181104
You can try the list comprehension. As the elements of your list are string, you must convert them into float :
def delta(in_list):
return [float(in_list[i+1]) - float(in_list[i]) for i in range(len(in_list) - 1)]
Part of me thinks it'd be more elegant to do this recursively, but the way you've done it is probably better if there's a very long list. Anyway, you're nearly there, you've just mixed up Python's for-loop syntax. for item in list gives you the items, for i in range(len(list)) gives indices to use with the list, which is what you want here.
def delta(in_list):
out_list = []
for i in range(len(in_list)-1):
out_list.append(in_list[i+1] - in_list[i])
return out_list
Just a list comprehension...
>>> in_list = [1, 1, 2, 3, 5, 8, 13, 21]
>>> [b - a for a, b in zip(in_list, in_list[1:])]
[0, 1, 1, 2, 3, 5, 8]

How could I indexing python list of lists without concatenating?

Assume I have input like this:
bl = [[0,1,2,3,4,5], [6,7,8,9], [10,11,12,13]]
idx = [10, 6, 3, 4, 9, 2]
and I want the output to be like this:
out = [[3,4,2], [6,9], [10]]
The logic behind is like this:
first I can view the lb_cat as some concatenated version:
lb_cat = [0,1,2,3,4,5,6,7,8,9,10,11,12,13]
Then index from the concatenated list:
pick = lb_cat[idx] = [10, 6, 3, 4, 9, 2]
At last, assigned the picked elements back to each group to get output of
out = [[3,4,2], [6,9], [10]]
The difficulty is that I cannot use operations like concatenated, since my input is not standard python list and it does not support concatenation operations.
What I want to do is to pick from a list of objects with the indices from the 'concatenated' view, but I actually pick from each of the elements of the list lb.
How could I do that in an efficient python way?
===========
Edit:
I have implemented a slow version, like this:
import numpy as np
bl = [[0,1,2,3,4,5], [6,7,8,9], [10,11,12,13]]
idx = [10, 6, 3, 4, 9, 2]
milestones = np.cumsum(np.array([len(el) for el in bl])).tolist()
milestones = [0,] + milestones
res = [[] for _ in bl]
for ix in idx:
for i, m in enumerate(milestones):
if ix < m:
res[i-1].append(ix)
break
This works for me, but it is too slow. Do I have a method to make it faster?
I am not sure if I understood your problem correctly, but I hope this will serve as a sufficient answer.
x=0 //to count the total number of numbers with concatination
out = [] //to store final result
for i in bl:
temp = []
for j in i:
if x in idx: //to check if you want xth indexed element
temp.append(j)
x+=1
if len(temp)>0: //only append if has an index in idx, i am not sure if you want this
out.append(temp)
print(out) //to print final output

Repeating same code block for creating different values

I'm making a program that basically calculates the missing values (x in this example) in multiple lists.
These are the lists:
L11=[1,3,5,'x',8,10]
L12=['x',3,3,'x',6,0]
L21=[6,1,1,9,2,2]
L22=[1,1,1,'x','x','x']
For example, I'm using this code block to find the x values in L22:
#How to find x:
#1--> a= calculate the sum of integers in the list
#2--> b=calculate the average of them
#3--> all values of x inside the list equal b
a22=L22.count('x')
for i in range(len(L22)):
if L22[i]=='x':
x_L22=round((sum([int(k) for k in L22 if type(k)==int]))/(len(L22)-a22))
So we find x_L22=1 and the new L22 is:
x_L22=1
L22=[1,1,1,1,1,1]
Now here is my question, I want to repeat this steps for all other lists without writing the same code. Is this possible?
Other answers focus on extracting your current code to a generic function which is useful but isn't neither sufficient nor necessary to apply the same piece of code on multiple input.
The only thing you need is to loop over your pieces of data :
L11=[1,3,5,'x',8,10]
L12=['x',3,3,'x',6,0]
L21=[6,1,1,9,2,2]
L22=[1,1,1,'x','x','x']
inputs = ( L11, L12, L21, L22 )
for input in inputs :
# your 4 previous lines on code, modified to work
# on the generic "input" instead of the specific "L22"
a=input.count('x')
for i in range(len(input)):
if input[i]=='x':
x=round((sum([int(k) for k in input if type(k)==int]))/(len(input)-a))
# or if you've extracted the above code to a function,
# just call it instead of using the above 4 lines of code.
try putting it in a function like this:
def list_foo(list_):
counted=list_.count('x')
for i in range(len(list_)):
if list_[i]=='x':
total=round((sum([int(k) for k in list_ if type(k)==int])) \
/(len(list_)-counted))
return total
use it in your main loop
x_L22 = list_foo(L22)
or x_L11 = list_foo(L11)
This is an excellent use case for functions in Python
def get_filled_list(list_of_numbers):
#How to find x:
#1--> a= calculate the sum of integers in the list
#2--> b=calculate the average of them
#3--> all values of x inside the list equal b
new_list=list_of_numbers.count('x')
for i in range(len(list_of_numbers)):
if list_of_numbers[i]=='x':
list_of_numbers = round(
(sum([int(k)
for k in list_of_numbers if type(k)==int]))/
(len(list_of_numbers)-new_list)
)
A11 = get_filled_list(L11)
# ,..
I'd write a function that receives a list as an input and returns the same list with the 'x' value replaced with a new value:
def calculateList(l):
nrX=l.count('x')
newList = []
for elem in l:
if elem == 'x':
x = int(round((sum([int(k) for k in l if type(k)==int]))/(len(l)-nrX)))
newList.append(x)
else:
newList.append(elem)
return newList
You can then call this function on all the list you have:
newL = calculateList(L22)
print(newL)
Output is:
[1, 1, 1, 1, 1, 1]
Or if you prefer you can create a list containing all the lists you want to evaluate:
allLists = [L11, L12, L21, L22]
And then you iterate over this list:
for l in allLists:
newL = calculateList(l)
print(newL)
Output is:
[1, 3, 5, 5, 8, 10]
[3, 3, 3, 3, 6, 0]
[6, 1, 1, 9, 2, 2]
[1, 1, 1, 1, 1, 1]

How to take the nth - (n-1)th term in Python?

I would like to know how to find the nth term - (n-1)th term within a list. I know it should be very simple, but I'm just having trouble with application. So given the input of [0, 2, 4, 6, 5], the function should return [0, 2, 2, 2, -1]. My solution (which doesn't work) is as follows:
def cost_to_diff (stocks):
for i in range(i+1):
stock[i] = stock[i] - stock[i-1]
print stock
Why doesn't this work as intended?
Your mistake is that you reset the ith element of list, so on the next cycle iteration you access it's changed value.
This will print what you need
def cost_to_diff (stocks):
for i in range(1, len(stocks)):
print stocks[i] - stocks[i-1]
If you want to print a list, then do
def cost_to_diff (stocks):
diff = []
for i in range(1, len(stocks)):
diff.append(stocks[i] - stocks[i-1])
print diff
or
def cost_to_diff (stocks):
print [stocks[i] - stocks[i-1] for i in range(1, len(stocks))]
Also I advice you to try numpy for such tasks. This function will do the job. Especially if you are playing with stock data, numpy will be much faster than lists. Moreover for stock data one usually uses data frames, so pandas is what you need to study, and Series.diff is the function you need.
You are using the wrong range. You need to find out the length of the stocks list, and then build your range accordingly.
differences = []
for i in range(len(stocks) - 1):
differences.append(stock[i+1] - stock[i])
print differences
However, there is a better way to do this. Python has several builtins to help you do this kind of stuff easily. Use the zip function to get your elements without messing around with indexes.
differences = []
for a, b in zip(l, l[:1]):
differences.append(b-a)
For example:
my_list = [0, 3, 4, 5, 7]
print zip(my_list, my_list[1:])
This produces output
[(0, 3), (3, 4), (4, 5), (5, 7)]
All you need to do after is subtract the elements.
The following code returns [2, 2, 2, -1] because I don't get why you will get 0 for the first element.
Do you assume that the first -1 element is also 0?
len('list') will give you the length of list.
range(start, end) will give you a range.
Since you like to start your iterations in the for loop at the second element (index = 1) start will be 1 and end will be the length of the stock list.
stock = [0,2,4,6,5]
result = []#create an empty list for the results
for i in range(1,len(stock)):#set the iteration steps, will be 1,2,3,4 in this case
result.append(stock[i] - stock[i-1])#By using stack[i] = ... you will overwrite the ith element
print result

Is it safe practice to edit a list while looping through it?

I was trying to execute a for loop like:
a = [1,2,3,4,5,6,7]
for i in range(0, len(a), 1):
if a[i] == 4:
a.remove(a[i])
I end up having an index error since the length of the list becomes shorter but the iterator i does not become aware.
So, my question is, how can something like that be coded? Can the range of i be updated in each iterations of the loop based on current array condition?
For the .pop() that you mention for example you can use a list comprehension to create a second list or even modify the original one in place. Like so:
alist = [1, 2, 3, 4, 1, 2, 3, 5, 5, 4, 2]
alist = [x for x in alist if x != 4]
print(alist)
#[1, 2, 3, 1, 2, 3, 5, 5, 2]
As user2393256 more generally puts it, you can generalize and define a function my_filter() which will return a boolean based on some check you implement in it. And then you can do:
def my_filter(a_value):
return True if a_value != 4 else False
alist = [x for x in alist if my_filter(x)]
I would go with the function solution if the check was too complicated to type in the list comprehension, so mainly for readability. The example above is therefore not the best since the check is very simple but i just wanted to show you how it would be done.
If you want to delete elements from your list while iterating over it you should use list comprehension.
a = [1,2,3,4,5,6,7]
a = [x for x in a if not check(x)]
You would need to write a "check" function that returns wether or not you want to keep the element in the list.
I don't know where you are going with that but this would do what I beleive you want :
i=0
a = [1,2,3,4,5,6,7]
while boolean_should_i_stop_the_loop :
if i>=len(a) :
boolean_should_i_stop_the_loop = False
#here goes what you want to do in the for loop
print i;
a.append(4)
i += 1

Categories