移动 XOR 运算符给出的 Python 中数组的所有元素位置

Shifting all element positions of an array in Python given by XOR operator

我想知道是否有一种方法可以在不遍历每个条目的情况下移动 numpy 数组的所有元素。我想要的转变是通过固定的 XOR 运算重新标记索引,形式如下:

import numpy as np 

N = 2

x = np.arange(2**(2 * N)).reshape(2**N, 2**N)
z = np.zeros((2**N, 2**N))

k = 1

for i in range(2**N):
    for j in range(2**N):
        z[i][j] = x[i ^ k][j ^ k]

我遇到的问题是后者我希望获取 N 的巨大值,如果我们希望遍历每个条目,这将成为瓶颈。非常感谢任何有关如何在单次射击中执行移动的建议。

根本没有理由在这里使用循环。你没有移动任何东西,问题在轴上是完全可分离的:

x = np.arange(2**(2 * N)).reshape(2**N, 2**N)
z = x[np.arange(2**N)[:, None] ^ k, np.arange(2**N) ^ k]

但是对于某些 a, b 来说,x[a, b] 是什么?从原来的定义可以看出是a * 2**N + b。因此,您可以插入 a = np.arange(2**N)[:, None] ^ kb = np.arange(2**N) ^ k 以避免生成除最终结果之外的任何内容:

idx = np.arange(2**N) ^ k
z = (idx[:, None] << N) + idx

<< N 代替 * 2**N 通常更快。

分配

此处显示的解决方案

None 预分配 z。但是,如果您要这样做,就像在最初的问题中一样,您应该注意类型。

z = np.zeros((2**N, 2**N))

这会默认创建一个浮点数组,这可能不是您想要的。

z = np.zeros((2**N, 2**N), dtype=int)

添加显式 dtype 使数组成为整数。然而,最简单的方法可能是

z = np.zeros_like(x)

由于您计划填写每个元素,因此您不需要浪费时间先用零填充它。 np.empty 在这种情况下提供了一个更好的选择:

z = np.empty((2**N, 2**N), dtype=int)

z = np.empty_like(x)