Numpy ring arrays



我一直在尝试学习numpy一段时间,并决定编写一些复杂的练习来验证我是否理解了一切,有一个对我来说似乎有点奇怪。

目标是编写一个只使用numpy库和numpy索引的函数(没有for/while循环,没有if语句),它将清除矩阵中所有的偶数环。

首先,我试着得到一个给定的环,这里有一个函数:这里m是矩阵,l是环的层数,0是环的外层

def get_ring(m, l):
n = m.shape[0]
return np.concatenate((m[l:n-l, l:n-l], m[(l+1):n-l, -(l+1)], m[-(l+1), -(l+2):l:-1], m[n-(l+1):l:-1, l]))
然后,我进一步编写了这个函数,使用np将一个环归零。其中的一些逻辑组成一个环的4个部分下面是这个函数
def zero_ring(m, l):
n = m.shape[0]
m[l:n-l, l:n-l] = np.where(np.logical_or(np.logical_or(np.arange(n-l-l)[:, None] == 0, np.arange(n-l-l) == n-l-l-1),
np.logical_or(np.arange(n-l-l)[::-1][:, None] == 0, np.arange(n-l-l)[::-1] == n-l-l-1)), 0, m[l:n-l, l:n-l])
return m

举个例子这是一个5x5数组的输出

print(zero_ring(a, 1))
[[ 1  2  3  4  5]
[ 6  0  0  0 10]
[11  0 13  0 15]
[16  0  0  0 20]
[21 22 23 24 25]]

现在剩下的就是写这个函数,把所有的偶数环归零,但是我不知道如果不使用for循环,我怎么能做到这一点,因为有了for循环,它将是立即的。

您的代码对我来说有点复杂,如果您可以将其扩展到多个环而无需任何手动循环。我认为如果你以分段的方式构建每个环,将很难实现,但请随意证明我是错的:)。

也就是说,我确实知道另一种有趣的方法来构建环状结构。考虑这个数组:

[3, 2, 1, 0, 1, 2, 3]

和数组中每对整数之间的最大值:

3  2  1  0  1  2  3
/---------------------
3 | 3  3  3  3  3  3  3 |
2 | 3  2  2  2  2  2  3 |
1 | 3  2  1  1  1  2  3 |
0 | 3  2  1  0  1  2  3 |
1 | 3  2  1  1  1  2  3 |
2 | 3  2  2  2  2  2  3 |
3 | 3  3  3  3  3  3  3 |
---------------------/

你要找的环就是这个数组中的偶数和奇数元素!

可以用np.abs+np.arange:

创建任意大小的1D数组。
def center(size):
return np.abs(np.arange(-size // 2 + 1, size // 2 + 1))
>>> center(7)
array([3, 2, 1, 0, 1, 2, 3])

并创建两个这样的数组之间的成对最大值,或者使用广播,或者使用np.maximum.outer。为了区分奇偶环,你可以用2取模。

def ring_mask(h, w):
rows = center(h)
cols = center(w)
return (np.maximum.outer(rows, cols) % 2).astype(bool)

最后,将掩码与np.where结合使用:

def zero_rings(arr):
mask = ring_mask(*arr.shape)
return np.where(~mask, arr, 0)
import numpy as np
arr = np.arange(1, 82).reshape(9, 9)
out = zero_rings(arr)

:

array([[ 1,  2,  3,  4,  5,  6,  7,  8,  9],
[10,  0,  0,  0,  0,  0,  0,  0, 18],
[19,  0, 21, 22, 23, 24, 25,  0, 27],
[28,  0, 30,  0,  0,  0, 34,  0, 36],
[37,  0, 39,  0, 41,  0, 43,  0, 45],
[46,  0, 48,  0,  0,  0, 52,  0, 54],
[55,  0, 57, 58, 59, 60, 61,  0, 63],
[64,  0,  0,  0,  0,  0,  0,  0, 72],
[73, 74, 75, 76, 77, 78, 79, 80, 81]])

PS:你可能需要也可能不需要反转掩码(或在% 2之前加1),这取决于你认为哪些环是偶数,哪些环是奇数。