【问题标题】:'Crop' a two dimensional array?“裁剪”二维数组?
【发布时间】:2012-11-02 22:07:19
【问题描述】:

我正在寻找一种高效的方法来裁剪二维数组。考虑这个例子:

我有一个构成 100x100 网格的二维数组。我只想退回一部分,60x60。这是一个“a”方式的示例,但我正在寻找指向最高性能方式的指针。

// Settings
var gridWidth = 100;
var gridHeight = 100;

// Populate Grid
var grid = [];

for(var i = 0; i<gridWidth; i++){
    grid[i] = [];
    for(var j = 0; j<gridHeight; j++){
        grid[i][j] = 0;
    }
}

// Crop Grid
var rect = {x:20,y:20,w:60,h:60};

var crop = [];
for(var i = rect.x; i<rect.x+rect.w; i++){
    crop[i-rect.x] = [];
    for(var j = rect.y; j<rect.y+rect.h; j++){
        crop[i-rect.x][j-rect.y] = grid[i][j];
    }
}

任何想法都非常感谢......

约翰

【问题讨论】:

    标签: javascript arrays multidimensional-array


    【解决方案1】:

    怎么样:

    function tab(n, func) {
        for (var a = [], i = 0; i < n; i++)
            a.push(func(i));
        return a;
    }
    
    function matrix(w, h, values) {
        return tab(h, function(y) {
            return tab(w, function(x) {
                return values(x, y);
            })
        })
    }
    
    grid = matrix(7, 10, function(x, y) {
        return x + ':' + y;
    })
    

    这给了我们:

    0:0 1:0 2:0 3:0 4:0 5:0 6:0
    0:1 1:1 2:1 3:1 4:1 5:1 6:1
    0:2 1:2 2:2 3:2 4:2 5:2 6:2
    0:3 1:3 2:3 3:3 4:3 5:3 6:3
    0:4 1:4 2:4 3:4 4:4 5:4 6:4
    0:5 1:5 2:5 3:5 4:5 5:5 6:5
    0:6 1:6 2:6 3:6 4:6 5:6 6:6
    0:7 1:7 2:7 3:7 4:7 5:7 6:7
    0:8 1:8 2:8 3:8 4:8 5:8 6:8
    0:9 1:9 2:9 3:9 4:9 5:9 6:9
    

    裁剪功能:

    function crop(mat, x, y, w, h) {
        return mat.slice(y, y + h).map(function(row) {
            return row.slice(x, x + w)
        })
    }
    
    cropped = crop(grid, 2, 1, 5, 6)
    

    结果:

    2:1 3:1 4:1 5:1 6:1
    2:2 3:2 4:2 5:2 6:2
    2:3 3:3 4:3 5:3 6:3
    2:4 3:4 4:4 5:4 6:4
    2:5 3:5 4:5 5:5 6:5
    2:6 3:6 4:6 5:6 6:6
    

    【讨论】:

      【解决方案2】:

      您可以尝试使用Array#slice [MDN],看看您是否获得了任何性能改进。还要尽量避免不必要的计算:

      var yend = rect.y + rect.h;
      var crop = [];
      
      for(var i = rect.x, j = 0, l = rect.x + rect.w; i < l; i++,j++){
          crop[j] = grid[i].slice(rect.y, yend);
      }
      

      您可以测试是否值得测试边缘情况。例如,如果 rect.x 和/或 rect.y0 并且您不再需要原始数组,您可以设置数组的 .length(修改它们):

      var rect = {x:0,y:0,w:60,h:60};
      
      grid.length = rect.w;
      
      for (var i = 0; i < rect.w; i++) {
          grid[i].length = rect.h;
      }
      

      【讨论】:

      • 我不确定,但第二个看起来并没有删除元素直到所需的 y 偏移量。
      • 啊该死...这只有在rect.y0 时才有效:-/ 那时可能会删除这个。
      【解决方案3】:

      试试这个方法:

      crop = grid.slice(rect.x, rect.x+rect.w);
      for(var i = 0; i<crop.length; i++){
          crop[i] = crop[i].slice(rect.y, rect.y+rect.h);
      }
      

      请注意,数组的维度现在为rect.w x rect.h,并且所有索引分别负偏移rect.xrect.y

      【讨论】:

      • 您的意思是写crop[i] = crop[i].splice(rect.y,rect.y+rect.h)?否则,索引只是从数组中删除...
      • @FelixKling 是的,谢谢。实际上,我刚刚意识到我应该使用slice,而不是splicesplice 返回移除的元素。
      • @FelixKling 不,我一开始就不应该使用splice。我需要slice,这是我的疏忽。
      • 哇...感谢 Asad 和 Felix 这么快的回复!看起来这是一个非常干净优雅的解决方案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-08-05
      • 2015-01-04
      • 2011-04-25
      • 1970-01-01
      • 2014-04-29
      • 2018-12-18
      • 2012-11-08
      相关资源
      最近更新 更多