初步答案,不可行
您可以轻松地将交换操作向量化,通过使用索引数组(c1,r1,c2,r2)而不是迭代标量索引列表。
c1 = np.array(<all the "c1" values>, dtype=int)
r1 = np.array(<all the "r1" values>, dtype=int)
c2 = np.array(<all the "c2" values>, dtype=int)
r2 = np.array(<all the "r2" values>, dtype=int)
A[c1, r1], A[c2, r2] = A[c2, r2], A[c1, r1]
请注意,这种方法会一次性完成所有交换操作,与迭代方式不同,如果交换顺序有所不同,则结果也会不同。因此,
这不是您问题的有效答案。
例如,将p1与p2交换,然后将p2与p3交换,与一次性交换p1和p2以及p2和p3是不同的。在后一种情况下,p1和p3都获得了p2的原始值,而p2获取了p1和p3之间值的
最后一个,即p3(根据它们在索引数组中出现的顺序)。
但是,由于您需要速度,将操作向量化(以某种方式)必须是正确的方法。
将正确性添加到上述解决方案
那么我们如何执行向量化交换,同时获得所需的输出呢?我们可以采用混合方法,将索引列表分成块(尽可能少的块),其中每个块仅包含唯一点,从而保证顺序无关紧要。对每个块进行向量化交换,并且我们只迭代块。
以下是如何实现的草图:
c1, r1 = np.array([ np.arange(10), np.arange(10) ])
c2, r2 = np.array([ [2,4,6,8,0,1,3,5,7,9], [9,1,6,8,2,2,2,2,7,0] ])
A = np.empty((15,15))
def get_chunk_boundry(c1, r1, c2, r2):
a1 = c1 + 1j * r1
a2 = c2 + 1j * r2
set1 = set()
set2 = set()
for i, (x1, x2) in enumerate(zip(a1, a2)):
if x1 in set2 or x2 in set1:
return i
set1.add(x1); set2.add(x2)
return len(c1)
while len(c1) > 0:
i = get_chunk_boundry(c1, r1, c2, r2)
c1b = c1[:i]; r1b = r1[:i]; c2b = c2[:i]; r2b = r2[:i]
print 'swapping %d elements' % i
A[c1b,r1b], A[c2b,r2b] = A[c2b,r2b], A[c1b,r1b]
c1 = c1[i:]; r1 = r1[i:]; c2 = c2[i:]; r2 = r2[i:]
如果一开始将索引存储为二维数组(N x 4),则在此处进行切片会更快。