高效地转置 JavaScript 数组

Gre*_*egA 2 javascript arrays prototype matrix

我写了这个方法来转置 javascript 数组

Array.prototype.transpose = function () {
   let rows = this.length;
   let cols = this[0].length;
   let ret = [[]];
   for (y=0;y<cols;y++)
     for (x=0;x<rows;x++)
       ret[y][x]=this[x][y]
   return ret;
}
Run Code Online (Sandbox Code Playgroud)

然而,这是非常低效的,因为它实际上复制了整个数据。

我更喜欢做的是使用一个标志transposed?,它会被认为arr[x][y]arr[y][x]打开的。

然后,该函数transpose就会切换它。

这如何在 javascript 中完成?

tri*_*cot 5

另一种选择可能是使用代理。它们允许您捕获对象成员访问(例如数组括号引用)并返回自定义值。

这是一个简单的实现,仅支持get访问索引和length属性,但不支持其他任何内容。如果你真的愿意,你可以扩展它来支持迭代、枚举、设置、数组方法(如joinmap、...)、...等,但如果你愿意走那么远,并且真的会使用这些类型方法,那么问题就真正变成了是否值得付出所有的努力,因为如果您像以前那样做,则总体性能可能会更好:将数组复制到其转置的对应部分中。

无论如何,这是:

var a = [ [1,2,3],
          [4,5,6] ];

a.transposed = new Proxy(a, {
    get: (arr, col) =>
        +col >= 0 ? new Proxy({ length: a.length }, {
                        get: (obj, row) => +row >=0 ? arr[row][col] : obj[row]
                    })
        : col == 'length'   ? arr[0] && arr[0].length
        : col == 'original' ? arr 
        : undefined
});

var t = a.transposed;
// Mutate a, to demo that also t shows the mutation:
a[0][2] = 3.5;
console.log('a = ', JSON.stringify(a));

console.log('a[0][2] = ', a[0][2], ', t[2][0] = ', t[2][0]);
console.log('a[0].length = ', a[0].length, ', t.length = ', t.length);
console.log('a.length = ', a.length, ', t[0].length = ', t[0].length);

// you can revert back to original array from the transposed one:
console.log('a === t.original?', a === t.original);
Run Code Online (Sandbox Code Playgroud)