我有一个(x,y)坐标的路径作为一个平面数组,如下所示:
[x1, y1, x2, y2, x3, y3, ...]
要将它从顺时针方向翻转到逆时针方向,我需要成对地反转它:x3,y3,x2,y2,x1,y1。以下工作并且启动速度非常快:
var a = ['x1', 'y1', 'x2', 'y2', 'x3', 'y3'];
for (var i = 0; i < (a.length/2); i = i + 2) {
var x = a[i];
var y = a[i+1];
a[i] = a[a.length - 2 - i];
a[i+1] = a[a.length - 1 - i];
a[a.length - 2 - i] = x;
a[a.length - 1 - i] = y;
};
但是有更优雅的方法吗?我和splice
玩了一会儿,但它将拼接的项目作为一个数组返回,并希望它们作为参数返回,这会破坏一些事情:
for (var i = 0; i < (a.length/2); i = i + 2) {
a.splice(i, 0, a.splice(a.length-2-i, 2)); // doesn't work
};
虽然我认为你可以通过创造性地使用apply
来解决这个问题,但是这个问题。
在x和y的数组中进行过滤,在每个数组上调用reverse并将它们拼接在一起似乎是可能的,但它在JS中非常冗长,并且可能效率低得多。
编辑:数组具有任意长度,可能包含数十万对,因此速度和内存使用非常重要。
答案 0 :(得分:2)
如果您使用两个计数器,一个从一开始就是一个,另一个从最后开始。
var a = ['x1', 'y1', 'x2', 'y2', 'x3', 'y3'];
for (var i = 0, j = a.length-2; i < j; i+=2, j-=2) {
var t1 = a[i],
t2 = a[i+1];
a[i] = a[j];
a[i+1] = a[j+1];
a[j] = t1;
a[j+1] = t2;
}
或者有点hackery,你可以稍微缩短它。
var a = ['x1', 'y1', 'x2', 'y2', 'x3', 'y3'];
for (var i = 0, j = a.length-2; i < j; i+=2, j-=2) {
a[ i ] = [a[ j ], a[ j ] = a[ i ]][0];
a[i+1] = [a[j+1], a[j+1] = a[i+1]][0];
}
让我们不要忘记解构分配。这将在ECMAScript 6中出现,但现在可以在Firefox中使用。
var a = ['x1', 'y1', 'x2', 'y2', 'x3', 'y3'];
for (var i = 0, j = a.length-2; i < j; i+=2, j-=2) {
[a[i], a[j], a[i+1], a[j+1]] = [a[j], a[i], a[j+1], a[i+1]];
}
另一种可能性是首先反转整个阵列,然后反转对。
var a = ['x1', 'y1', 'x2', 'y2', 'x3', 'y3'];
a.reverse();
for (var i = 0; i < a.length; i+=2) {
var t = a[i];
a[i] = a[i+1];
a[i+1] = t;
}
可能比较慢,但肯定更清洁。
或者为结果使用单独的数组可以消除临时变量。
var a = ['x1', 'y1', 'x2', 'y2', 'x3', 'y3'];
var b = new Array(a.length);
for (var i = 0, j = a.length-2; i <= j; i+=2, j-=2) {
b[j] = a[i],
b[j+1] = a[i+1];
b[i] = a[j];
b[i+1] = a[j+1];
}
使用其全长初始化数组可以在现代实现中提高性能。
答案 1 :(得分:1)
如果你引入一个交换辅助函数,Cookie怪物的算法实际上变得更快,更具可读性和DRYer:
function swap(ary, x, y) {
var t = ary[x];
ary[x] = ary[y];
ary[y] = t;
}
function helperDualCounterPairwiseReverse(coords) {
var a = coords.slice(0);
for (var i = 0, j = a.length-2; i < j; i+=2, j-=2) {
swap(a, i, j);
swap(a, i+1, j+1);
};
return a;
}
这是另一个可读但性能较差的变体:
function semanticPairwiseReverse(coords) {
var prev, reversed = [];
for (var i = 0; i < coords.length/2 + 2; i = i + 2) {
reversed.unshift(coords[i], coords[i + 1]);
};
return reversed;
}
如果您只处理3D数据集并且过度关注性能问题,那么您可能需要考虑一个&#34; dumb&#34;你硬交换代码的方法:
function dumbPairwiseReverse(coords) {
var reversed = coords.slice(0); // Duplicates the coordinate list
reversed[0] = coords[4]; reversed[4] = coords[0];
reversed[1] = coords[5]; reversed[5] = coords[1];
return reversed;
}
以上是上述的一些基准以及其他呈现的解决方案:http://jsperf.com/pairwise-reverse/5