反转平面坐标数组

时间:2014-03-27 04:25:44

标签: javascript arrays coordinates reverse

我有一个(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中非常冗长,并且可能效率低得多。

编辑:数组具有任意长度,可能包含数十万对,因此速度和内存使用非常重要。

2 个答案:

答案 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