Can't Modify List Elements in a Loop

Can't modify list elements in a loop

Because the way for i in li works is something like this:

for idx in range(len(li)):
i = li[idx]
i = 'foo'

So if you assign anything to i, it won't affect li[idx].

The solution is either what you have proposed, or looping through the indices:

for idx in range(len(li)):
li[idx] = 'foo'

or use enumerate:

for idx, item in enumerate(li):
li[idx] = 'foo'

How to modify list entries during for loop?

It's considered poor form. Use a list comprehension instead, with slice assignment if you need to retain existing references to the list.

a = [1, 3, 5]
b = a
a[:] = [x + 2 for x in a]
print(b)

How to change values in a list while using for loop in Python? (without using index)

Python unlike many other languages is dynamically typed as in you don't need to initialize prepopulated arrays(lists) before populating them with data. Also a standard convention is list comprehensions which in lamens are in-line loops that return a list.

a = [1,2,3,4,5]
b = [num * 4 for num in a]

This is equivilent to:

a = [1,2,3,4,5]
b = []
for num in a:
b.append(num * 4)

List items are not changed in for loop

You can go through by index and modify in place that way

for i, _ in enumerate(lines_list):
lines_list[i] = lines_list[i].strip()

though I think many would prefer the simplicity of duplicating the list if the list isn't so big that it causes an issue

lines_list = [line.strip() for line in lines_list]

The issue is using the = operator reassigns to the variable line, it doesn't do anything to affect the contents of the original string. New python programmers are equally as often surprised when:

for i in range(10):
print(i)
i += 1

prints the numbers 0,1,2,3,4,5,6,7,8,9. This occurs because the for loop reassigns i at the beginning of each iteration to the next element in the range. It's not exactly your problem, but it's similar.

Since you are reading lines out of a file, and stripping them afterwards, really what you should do is

with open(file_name) as f:
lines_list = [line.strip() for line in f]

which reads and strips one line at a time, rather than reading everything first, then stripping the lines afterwards

Modify list values in a for loop

It's not because of the np.clip function. It's because you use loop on a list of mutable, so the value of the element can be modified. You can see here Immutable vs Mutable types for more information.

Modify a list while iterating

You are not modifying the list, so to speak. You are simply modifying the elements in the list. I don't believe this is a problem.

To answer your second question, both ways are indeed allowed (as you know, since you ran the code), but it would depend on the situation. Are the contents mutable or immutable?

For example, if you want to add one to every element in a list of integers, this would not work:

>>> x = [1, 2, 3, 4, 5]
>>> for i in x:
... i += 1
...
>>> x
[1, 2, 3, 4, 5]

Indeed, ints are immutable objects. Instead, you'd need to iterate over the indices and change the element at each index, like this:

>>> for i in range(len(x)):
... x[i] += 1
...
>>> x
[2, 3, 4, 5, 6]

If your items are mutable, then the first method (of directly iterating over the elements rather than the indices) is more efficient without a doubt, because the extra step of indexing is an overhead that can be avoided since those elements are mutable.

Modifying list while iterating

I've been bitten before by (someone else's) "clever" code that tries to modify a list while iterating over it. I resolved that I would never do it under any circumstance.

You can use the slice operator mylist[::3] to skip across to every third item in your list.

mylist = [i for i in range(100)]
for i in mylist[::3]:
print(i)

Other points about my example relate to new syntax in python 3.0.

  • I use a list comprehension to define mylist because it works in Python 3.0 (see below)
  • print is a function in python 3.0

Python 3.0 range() now behaves like xrange() used to behave, except it works with values of arbitrary size. The latter no longer exists.

Why doesn't the array change when I try to modify it via a for-loop

"I'm struggling to understand why the following doesn't change the existing array?"

I take it your actual question is why what you have tried doesn't work, and not specifically how to do it right, but I will address both.

The reason, as I understand it, is that while the x variable is, on each iteration assigned the result you are looking for (x[:5]) that result is not stored in your data array. It is simply stored in the x variable, during that single iteration, which is a copy of the element in the array, not a reference to the element itself. It is not the same as doing

for i in range(len(data)):
data[i] = data[i][:5] # explicitly sets the element

which explicitly sets the array elements

As confirmation, see this:

data = [[1,2,3,4], [5,6,7,8]]
for x in data:
x = x[:2] # does indeed set x, but only x
print(x)

[1,2]
[5,6]
>> print(data) # but data array is unchanged
[[1,2,3,4], [5,6,7,8]

Alternatively, see this (list comprehension):

data = [x[:5] for x in data]  
# this creates a new array, and stores it in data, but has the outcome you want

Modifying a list while iterating over it - why not?

while len(mylist) > 0:
print mylist.pop()

You are not iterating over the list. You are each time checking an atomic condition.

Also:

while len(mylist) > 0:

can be rewritten as:

while len(mylist):

which can be rewritten as:

while mylist:


Related Topics



Leave a reply



Submit