2012-11-14 1 views
5

Sto cercando un modo molto performante per ritagliare un array bidimensionale. Considerare questo esempio:'Ritaglia' un array bidimensionale?

Ho una matrice bidimensionale che costituisce una griglia 100x100. Voglio solo restituire solo un ritaglio di esso, 60x60. Ecco un esempio di "un" modo per farlo, ma sto cercando dei puntatori al modo più performante per farlo.

// 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]; 
    } 
} 

Ogni pensiero molto apprezzato ...

John

risposta

2

provare in questo modo:

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); 
} 

noti che le dimensioni della matrice sono ora rect.w x rect.h, e tutti gli indici sono negativamente compensate rispettivamente rect.x e rect.y.

+0

Intendevi scrivere 'crop [i] = crop [i] .splice (rect.y, rect.y + rect.h)'? Altrimenti, gli indici vengono appena rimossi dall'array ... –

+0

@FelixKling Yup, grazie. In realtà, ho appena realizzato che avrei dovuto usare 'slice', non' splice'. 'splice' restituisce elementi rimossi. –

+0

Si dovrebbe anche ricordare che questo modificherà l'array originale ... –

0

Si può provare a utilizzare Array#slice[MDN] e vedere se si guadagna eventuali miglioramenti delle prestazioni. Anche cercare di evitare calcoli inutili:

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); 
} 

Si potrebbe testare se vale la pena di prova per i casi limite. Per esempio, se rect.x e/o rect.y sono 0 e non hai bisogno di più la matrice originale, si può solo impostare la .length della matrice (s) (che li modifica):

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; 
} 
+0

Non sono sicuro, ma quella seconda non sembra che rimuova gli elementi fino allo spostamento y desiderato. –

+0

Ah dannazione ... Funzionerebbe solo se 'rect.y' è' 0': -/Probabilmente cancellerò questo poi. –

2

ne dite:

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; 
}) 

questo ci dà:

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 

La funzione di ritaglio:

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) 

risultato:

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