Nested loop won't update [duplicate] - python

This question already has answers here:
Multiply every element in a nested list by a constant
(3 answers)
Closed 6 months ago.
i'm trying to multiply all items in a list by -1, but the list won't update.
the original list goes like:
[[[[-0.04344771 -0.07890235 -0.08350667 ... -0.05058916 -0.02590174
0.01833121]
[-0.03187432 -0.06377442 -0.07528157 ... -0.0153968 0.00928687
0.05289121]
[-0.0030058 -0.02783908 -0.04554714 ... 0.01647086 0.02895362
0.05640405]
...
[ 0.00193604 0.03679746 0.06137059 ... 0.04944649 0.06763638
0.08346977]
[ 0.01469174 0.04900428 0.0724168 ... 0.09451687 0.08840736
0.0754609 ]
[ 0.0307981 0.05116013 0.06343959 ... 0.08668113 0.05572119
0.01737073]]]]
i try to update it with:
for value in data:
for a in value:
for b in a:
for item in b:
item = item * -1
but when i try to print the list again, nothing has changed.
When i try to print it however, with:
for value in data:
for a in value:
for b in a:
print(b * -1)
it does print the list correctly:
[-0.0307981 -0.05116013 -0.06343959 ... -0.08668113 -0.05572119
-0.01737073]
how do i fix this?

You assign to variable, not to list content. You can assign to i-th element of list instead:
for value in data:
for a in value:
for b in a:
for i, item in enumerate(b):
b[i] = -item
Or use augmented assignment to list item:
for value in data:
for a in value:
for b in a:
for i in range(len(b)):
b[i] *= -1

This happens because the line
for item in b
copies the value of the item in the innermost array, rather than directly referencing it. For an array that is nested specifically three deep, you'd need to do something like this:
for i in range(len(x)):
for j in range(len(x[i])):
for k in range(len(x[i][j])):
for l in range(len(x[i][j][k])):
x[i][j][k][l] *= -1
This changes the actual values rather than creating a copy, since the line x[i][j][k][l] *= -1 changes the value stored in the array as opposed to a copy

Related

printing a new list as product of elements in two lists [duplicate]

This question already has answers here:
How can I use `return` to get back multiple values from a loop? Can I put them in a list?
(2 answers)
Element-wise addition of 2 lists?
(17 answers)
Closed 28 days ago.
So i'm trying to define a function which given two lists of the same size, returns a new list with the product of each element at a given index.
a = [1, 2, 3]
b = [1, 4, 5]
def list_mult(a, b):
if len(a) != len(b):
print("error, lists must be the same size")
for i in range(len(a)):
return [a[i] * b[i]]
print(list_mult(a, b))
The code is running, but it is only returning [1]. Not sure why, as I was under the impression that this for loops iterates over all i's in the range.
Don't return from inside the loop, as that will return after only 1 iteration. Keeping your current structure, you can instead add each product to a list and return that.
res = []
for i in range(len(a)):
res.append(a[i] * b[i])
return res
Alternatively, use a list comprehension with zip.
return [x * y for x, y in zip(a, b)]
Here's how I would solve the problem, catering for the edgecase of one array being larger than the other.
from typing import List
def multiply_arrays(a: List[int], b: List[int]):
result = []
for i in range(max(len(a), len(b))):
item_a = a[i] if i < len(a) else 1
item_b = b[i] if i < leb(b) else 1
result.append(item_a * item_b)
return result

Is it possible to modify the list itself, not its copy? [duplicate]

This question already has answers here:
How to modify list entries during for loop?
(10 answers)
How to remove items from a list while iterating?
(25 answers)
Closed 1 year ago.
I need to write a function which removes odd numbers from a list and square remaining even numbers.
I've tried something like this:
def modify_list(l):
l1 = [i ** 2 for i in l if i % 2 == 0]
return l1
but it creates a copy from a list that I've passed to a function, whereas I need to modify the passed list itself, so the following code would result:
id(l1) == id(l) # True
I've also tried to rewrite the code using remove method, but I couldn't figure out how to square remaining elements from passed list so it would return the same list (not its copy)
def modify_list(l):
for element in l:
if element % 2 != 0:
l.remove(element)
Is it possible to change my code in order to return the same list object that I've passed, but without odd numbers and with squared even numbers?
def modify_list(l):
li = [i**2 for i in l if i % 0 == 0]
for n,i in enumerate(li):
l[n] = i
return l
lists are mutable so a direct assignment works. 'li' is a new list so will have a different id.

What is the correct loop range

I want to delete some array from list. But I'm using wrong range.
At start the range is correct.
This should work, if string in variable result[b][2:3] then delete result[b]
for b in range(len(result)):
if 'FillLevel' in result[b][2:3]:
del result[b]
After that I have error: IndexError: list index out of range
I want to find this string and delete whole line (array):
V;4;FillLevel[1];CPUA.DB1610.0,I0,64;RW
V;4;FillLevel[2];CPUA.DB1610.0,I;RW
V;4;FillLevel[5];CPUA.DB1610.6,I;RW
V;4;FillLevel[6];CPUA.DB1610.8,I;RW
V;4;FillLevel[11];CPUA.DB1610.18,I;RW
Why this code:
print(result[4][2:3])
print(result[5][2:3])
print(result[6][2:3])
print(result[7][2:3])
print(result[8][2:3])
print(result[9][2:3])
print(result[10][2:3])
b = 0
while b < len(result):
if 'FillLevel' in result[b][2:3]:
del result[b]
del adress[b]
print('yes')
b += 1
Showing only once 'yes' ?
['FillLevel']
['FillLevel[1]']
['FillLevel[2]']
['FillLevel[3]']
['FillLevel[4]']
['FillLevel[5]']
['FillLevel[6]']
yes
The issue is that del result[b] changes the composition (and the length of) result, thereby interfering with your loop.
Perhaps the easiest way to fix this is by rephrasing your code as a list comprehension:
result = [r for r in result if 'FillLevel' not in r[2:3]]
Alternatively, you could fix it by iterating in reverse:
for b in range(len(result) - 1, -1, -1):
if 'FillLevel' in result[b][2:3]:
del result[b]
Let's say there are 10 items in the list.
Half-way through you delete one of the items; now there are 9 items in the list.
In the last cycle, your loop asks for the tenth item. My guess is that's where the index error is happening (though it could be due to the [2:3] call as well, depending on the contents of your list)
A more pythonic solution would be
result = [val for val in result if 'FillLevel' not in val[2:3]]
If you want to preserve the same list and parse it in the strait order you can use a while loop which evaluate the len(result) in each iteration
b = 0
while b < len(result) :
if 'FillLevel' in result[b][2:3]:
del result[b]
b += 1
for first
- it's mach easyer to iterate by list withot getting length, probably you are got an error coz length of list is changing during loop
for second
- you are trying to check 'FillLevel' in slice of string. slice return one character
- try to not midify your list but make new one with filtered items
like this:
new_list = []
for b in result:
if 'FillLevel' not in b:
new_list.append(b)
or check about List Comprehensions and type this:
[i for i in result if 'FillLevel' not in i]

Multiply every other element in a list

I have a list, let's say: list = [6,2,6,2,6,2,6], and I want it to create a new list with every other element multiplied by 2 and every other element multiplied by 1 (stays the same).
The result should be: [12,2,12,2,12,2,12].
def multi():
res = 0
for i in lst[0::2]:
return i * 2
print(multi)
Maybe something like this, but I don't know how to move on from this. How is my solution wrong?
You can use slice assignment and list comprehension:
l = oldlist[:]
l[::2] = [x*2 for x in l[::2]]
Your solution is wrong because:
The function doesn't take any arguments
res is declared as a number and not a list
Your loop has no way of knowing the index
You return on the first loop iteration
Not related to the function, but you didn't actually call multi
Here's your code, corrected:
def multi(lst):
res = list(lst) # Copy the list
# Iterate through the indexes instead of the elements
for i in range(len(res)):
if i % 2 == 0:
res[i] = res[i]*2
return res
print(multi([12,2,12,2,12,2,12]))
You can reconstruct the list with list comprehenstion and enumerate function, like this
>>> [item * 2 if index % 2 == 0 else item for index, item in enumerate(lst)]
[12, 2, 12, 2, 12, 2, 12]
enumerate function gives the current index of them item in the iterable and the current item, in each iteration. We then use the condition
item * 2 if index % 2 == 0 else item
to decide the actual value to be used. Here, if index % 2 == 0 then item * 2 will be used otherwise item will be used as it is.

Python: Iterate through a list by value, not by index

How can I iterate through by something other than the index?
I have
L = [[1,2,3],[5,3,6],[5,4,14],[23,5,2],....,[11,13,6]]
notice how the middle element is increasing always by 1. the outer elements are pretty much random.
I want to be able to say something like this:
for i in L[2:4]:
which would iterate through the elements: [1,2,3],[5,3,6],[5,4,14], as opposed to looking at 2:4 as indexes.
so obviously the syntax of my for loop is incorrect. How can I do this?
[item for item in L if 2 <= item[1] <= 4]
is one way of doing it
def slice_special(a_list,slice_idx,minimum_value,maximum_value):
return [item for item in a_list if minimum_value <= item[slice_idx] <= maximum_value]
print slice_special(L,1,2,4)
or something more sophisticated like a dedicated data structure
class MyDataStructure:
def __init__(self,a_list):
self.my_data = a_list
def __getitem__(self,arg):
if isinstance(arg,slice):
return [item for item in self.my_data if arg.start <= item[arg.step] <= arg.stop]
raise Exception("%s is unscriptable"%self)
print MyDataStructure([[1,2,3],[5,3,6],[5,4,14],[23,5,2]])[2:4:1]
If you know the size of the elements of the list, you can unpack the sublists into the iteration variables:
>>> L = [[1,2,3],[5,3,6],[5,4,14],[23,5,2]]
>>> for a, b, c in L:
... print(a,b,c)
...
1 2 3
5 3 6
5 4 14
23 5 2
>>>
If you don't want to use a certain index, you can assign it to _, which is the standard way of notating unused variables.

Categories