顺时针对ndarray进行排序的Numpyic方法?
我正在尝试顺时针(按升序)对 numpy ndarray 进行排序。您可以将其理解为获取数组中的所有值,对它们进行排序,然后将它们按顺时针螺旋排列成具有相同形状的新数组。顺时针螺旋的方向如下图所示:
例如,假设我有一个数组
import numpy as np
a1 = np.array(([2, 4, 6],
[1, 5, 3],
[7, 9, 8]))
预期的输出是
np.array([[1, 2, 3],
[8, 9, 4],
[7, 6, 5]])
如果我有一个数组
a2 = np.array(([2, 4, 6],
[1, 5, 3],
[7, 9, 8],
[12, 11, 10]))
预期的输出是
np.array([[1, 2, 3],
[10, 11, 4],
[9, 12, 5],
[8, 7, 6]])
到目前为止我尝试过的
我的想法是跟踪移动迭代器的行索引x和列索引y以及cur排序后的扁平列表的当前索引sa。移动迭代器水平通过行和垂直lenr通过列时,将通过 ( lenc)的行数和通过 ( ) 的列数减去。这是我设法编写的函数:1lenrlenc
def clockwise_sorted(a, key=None, reverse=False):
nr, nc = a.shape
res = a.tolist()
sa = a.ravel().tolist()
if key is None:
sa.sort(reverse=reverse)
else:
sa.sort(key=key, reverse=reverse)
res[0] = sa[:nc]
cur, lenr, lenc = nc, nr - 1, nc - 1
x, y = 0, nc - 1
while (lenc > 0 and lenr > 0):
# go down, then go left
for _ in range(lenr):
x += 1
res[x][y] = sa[cur]
cur += 1
for _ in range(lenc):
y -= 1
res[x][y] = sa[cur]
cur += 1
lenr -= 1
lenc -= 1
# go up, then go right
for _ in range(lenr):
x -= 1
res[x][y] = sa[cur]
cur += 1
for _ in range(lenc):
y += 1
res[x][y] = sa[cur]
cur += 1
lenr -= 1
lenc -= 1
return np.array(res)
对于方阵,我的代码工作正常:
print(clockwise_sorted(a1))
#[[1 2 3]
# [8 9 4]
# [7 6 5]]
#%timeit 5.98 µs ± 413 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
但它不适用于非方阵:
print(clockwise_sorted(a2))
#[[ 1 2 3]
# [10 11 4]
# [ 9 9 5]
# [ 8 7 6]]
显然,它错过了12at [2,1]。
请注意,我不希望您理解并修复我的代码。我不太喜欢我的代码,因为我觉得应该有更多的 numpyic 方法来做到这一点。因此,我想看到一些 numpyic 解决方案。但是,如果有人可以评论我的代码有什么问题,那就太好了。
回答
您可以使用numpy.rot90递归在数组上顺时针旋转。修改成1d后对数组的值进行排序,通过它编辑数组中的值
def rotate(matrix, arr):
if not len(matrix):
return
matrix[0] = arr[:len(matrix[0])]
rotate(np.rot90(matrix[1:]), arr[len(matrix[0]):])
a1 = np.array(([2, 4, 6],
[1, 5, 3],
[7, 9, 8]))
sorted_arr = sorted(a1.ravel())
rotate(a1, sorted_arr)
print(a1)
输出
[[1 2 3]
[8 9 4]
[7 6 5]]