stackoverflowuser2010
stackoverflowuser2010

Reputation: 40899

Update array while inside for loop over arrays

I have a Numpy array and can successfully update all its elements with one line:

array_1 = np.array([1, 2, 3, 4])
array_1 = array_1 / 10.0

print(array_1)
# [0.1 0.2 0.3 0.4] -- Success!

However, when I have a list of Numpy arrays and iterate over them with a for in loop, I cannot apply the same operation and get back the desired results.

array_1 = np.array([1, 2, 3, 4])
array_2 = np.array([5, 6, 7, 8])
array_3 = np.array([9, 10, 11, 12])

print(array_1) # [1 2 3 4]
print(array_2) # [5 6 7 8]
print(array_3) # [ 9 10 11 12]

for array in [array_1, array_2, array_3]:
    array = array / 10.0

print(array_1) # [1 2 3 4] -- No changes??
print(array_2) # [5 6 7 8]
print(array_3) # [ 9 10 11 12]

Why am I unable to update these arrays inside a loop? My understanding is that in the line

for array in [array_1, array_2, array_3]:

array will be a pointer to each of the three Numpy arrays.

How can I fix this problem?

Upvotes: 1

Views: 2873

Answers (2)

0x263A
0x263A

Reputation: 1859

You can make a shallow copy of the target array inside the for loop to edit the original.

for array in [array_1,array_2,array_3]:
    array[:] = array / 10.0

EDIT With Explanation---

In the for loop the control variable is its own object that deep copies the item being iterated over. We can use the [:] operation to make a shallow copy of the target item that references the original object. The following code demonstrates this concept:

array_1 = ['foo']
print(id(array_1)) # Original object id
for array in [array_1]:
    array = [1]
    print(id(array)) # Deep copy id
for array in [array_1]:
    array[:] = [1]
    print(id(array)) # Original object id

Upvotes: 2

Max Shouman
Max Shouman

Reputation: 1331

Becuse you're only assigning new values to the control variable of the loop, so you need to address the actual elements by indexing:

arrays = [array_1, array_2, array_3]

for i in range(len(arrays)):
    arrays[i] = arrays[i] / 10.0

or even more comprehensively:

arrays = [array / 10.0 for array in arrays]

or even by filtering:

arrays = list(filter(lambda x: x / 10.0, arrays))

EDIT:

As @ForceBru noted in the comments section, in-place division would force the return of a float type array whereas the original is int. So the following was changed in the first code snippet: arrays[i] /= 10.0 -> arrays[i] = arrays[i] / 10.0

Upvotes: 1

Related Questions