简体   繁体   English

遍历数组列表,同时对每个数组进行更改

[英]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. 您需要记住几件事。

  • how Python assigns values to variables Python如何将值分配给变量
  • how Python assigns values to an iteration variable Python如何将值分配给迭代变量
  • what functions like 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: 可以使用列表更改onetwo的唯一方法是一系列操作,例如:

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]将这些新数组分配给变量onetwo 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM