[英]Iterating over a list of arrays while making changes to each array
This is a follow-up post from a previous question of mine: Referring to arrays in a for-loop . 这是我的上一个问题的后续文章: 在for循环中引用数组 。
I would like to generalize the solution proposed there in order to be able to complete more complex tasks, such as attaching a column to each array that contains the result of some calculation: 我想对在那里提出的解决方案进行概括,以便能够完成更复杂的任务,例如将一列附加到包含某些计算结果的每个数组上:
import numpy as np
list=[one, two, three]
for arr in list:
arr=np.column_stack([arr,5*arr[:,2]-arr[:,1])])
All three arrays have the same dimensions. 所有三个阵列都具有相同的尺寸。
In [59]: one=np.arange(6).reshape(2,3)
In [60]: two=np.arange(6).reshape(2,3)
Forget about the loop for the moment, and just try to change one
: 暂时忘记循环,然后尝试更改
one
:
In [61]: arr = one
In [62]: arr=np.column_stack([arr,5*arr[:,2]-arr[:,1]])
In [63]: arr
Out[63]:
array([[ 0, 1, 2, 9],
[ 3, 4, 5, 21]])
In [65]: one
Out[65]:
array([[0, 1, 2],
[3, 4, 5]])
This action has changed arr
, but not one
. 这一举措改变了
arr
,而不是one
。 Originally arr
referenced the same object ( ndarray
) as one
, but after the new assignment, it referenced a new array. 原本
arr
引用的同一对象( ndarray
)为one
,但新分配之后,它引用的新的数组。
In 在
for arr in alist:
arr = ....
arr
is assigned an element of alist
. arr
分配了一个alist
元素。 But then in the loop it is assigned another something else, without changing the original object. 但是,然后在循环中为其分配了其他内容,而不更改原始对象。 On the next iteration,
arr
is assigned the next element in the list, and so on. 在下一次迭代中,为
arr
分配了列表中的下一个元素,依此类推。
You need to keep in mind several things. 您需要记住几件事。
column_stack
to column_stack
这样的功能 In your previous question 在上一个问题中
In [69]: for arg in [one,two]:
...: arg[:,1:] += 10
...:
In [70]: one
Out[70]:
array([[ 0, 11, 12],
[ 3, 14, 15]])
In [71]: two
Out[71]:
array([[ 0, 11, 12],
[ 3, 14, 15]])
this works because the arg[:,1:] += 10
is modifying the array currently assigned to arg
. 这之所以有效,是因为
arg[:,1:] += 10
正在修改当前分配给arg
的数组。 An array is mutable
; 数组是
mutable
; element values can be changed in-place. 元素值可以就地更改。
np.column_stack()
does not act in-place. np.column_stack()
不能就地执行。 It makes new array. 它制作了新的数组。
About the only way that you can change one
and two
with a list is a sequence of operations like: 可以使用列表更改
one
和two
的唯一方法是一系列操作,例如:
In [72]: newlist=[np.column_stack([arr,5*arr[:,2]-arr[:,1]]) for arg in [one,two]]
In [73]: newlist
Out[73]:
[array([[ 0, 1, 2, 9, 9],
[ 3, 4, 5, 21, 21]]), array([[ 0, 1, 2, 9, 9],
[ 3, 4, 5, 21, 21]])]
In [74]: one
Out[74]:
array([[ 0, 11, 12],
[ 3, 14, 15]])
In [75]: one, two = newlist
In [76]: one
Out[76]:
array([[ 0, 1, 2, 9, 9],
[ 3, 4, 5, 21, 21]])
In[72]
creates a new list, with new arrays. In[72]
创建具有新数组的新列表。 In[75]
assigns these new arrays to the variables one
and two
. In[75]
将这些新数组分配给变量one
和two
。 This wipes out their previous references. 这消除了他们以前的参考。 In effect I did
one=[np.column_stack([one,5*one[:,2]-one[:,1]])
, and similarly for two
. 实际上,我做了
one=[np.column_stack([one,5*one[:,2]-one[:,1]])
,类似地对two
。
Assigning to the variable doesn't update the list, it's just a temporary reference to the value that's in the array. 分配给变量不会更新列表,它只是对数组中值的临时引用。
Use enumerate
to get the list index, then you can replace it with the result. 使用
enumerate
获取列表索引,然后可以将其替换为结果。
for index, arr in enumerate(myList):
myList[index] = np.column_stack([arr,5*arr[:,2]-arr[:,1])])
Also, avoid using the names of built-in classes and functions as your own variable names. 另外,请避免将内置类和函数的名称用作自己的变量名。
list
is a standard class. list
是一个标准类。
Don't forget that in Python, variables are references to values. 不要忘记在Python中,变量是对值的引用。 The iteration variable is a variable, so assigning a new value to this variable do not change the iterable.
迭代变量是一个变量,因此为该变量分配新值不会更改可迭代项。
In this case, why not use lists comprehensions ? 在这种情况下,为什么不使用列表推导呢?
import numpy as np
my_list = [one, two, three]
my_list = [np.column_stack([arr,5*arr[:,2]-arr[:,1])]) for arr in list]
And please, don't shadow list
type… 而且请不要遮盖
list
类型…
I'm afraid the solution you are referencing can only be generalized to in-place changes to the array. 恐怕您引用的解决方案只能推广到就地更改数组。 Anything that changes the size will AFAIK create a new array.
更改大小的任何操作都会自动创建新数组。
So this 所以这
>>> X,Y,Z = (np.arange(i+1, i+10, dtype=float).reshape(3, 3) for i in range(3))
>>> L = [X,Y,Z]
>>> for arr in L:
... np.sin(arr, out=arr)
or this 或这个
>>> for arr in L:
... arr[1] = arr[1, ::-1]
will work. 将工作。
You can even replace the entire array, as long as you do it in-place: 您甚至可以替换整个阵列,只要就地执行即可:
>>> for arr in L:
... arr[...] = 1.7
But this 但是这个
>>> for arr in L:
... np.append(arr, arr[-1])
will not change the original arrays but create new ones. 不会更改原始数组,而是创建新数组。 Assigning back to
arr
won't help because it just rebinds the name arr
to the new object. 分配回
arr
将无济于事,因为它将名称arr
重新绑定到了新对象。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.