2012-11-14 15 views
5

Poszukuję wysoce wydajnego sposobu przycinania tablicy dwuwymiarowej. Rozważmy ten przykład:"Przytnij" tablicę dwuwymiarową?

Mam dwuwymiarową tablicę, która tworzy siatkę 100x100. Chcę tylko zwrócić, 60x60. Oto przykład "sposobu", aby to zrobić, ale szukam wskazówek do najbardziej wydajnego sposobu robienia tego.

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

Wszelkie myśli mile widziana ...

John

Odpowiedz

2

Wypróbuj za to sposób:

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

Należy zauważyć, że wymiary macierzy są teraz rect.w x rect.h i wszystkie współczynniki są ujemnie skompensowany rect.x i rect.y odpowiednio.

+0

Czy chciałeś napisać 'crop [i] = crop [i] .splice (rect.y, rect.y + rect.h)'? W przeciwnym razie indeksy są po prostu usuwane z tablicy ... –

+0

@FelixKling Yup, dzięki. Właściwie to po prostu zdałem sobie sprawę, że powinienem używać 'plaster', a nie' splice'. 'splice' zwraca usunięte elementy. –

+0

Należy również wspomnieć, że zmodyfikuje to oryginalną tablicę ... –

0

Można spróbować użyć Array#slice[MDN] i zobacz, czy można uzyskać żadnych ulepszeń wydajności. Również unikać niepotrzebnych obliczeń:

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

Można sprawdzić, czy warto przetestować przypadków brzegowych. Na przykład, jeśli rect.x i/lub rect.y0 i nie trzeba oryginalną tablicę już, można po prostu ustawić .length tablicy (ów) (który je modyfikuje):

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

Nie jestem pewien, ale ten drugi nie wygląda na to, że usuwa elementy do pożądanego przesunięcia y. –

+0

Ah darn ... Działa to tylko wtedy, gdy 'rect.y' to' 0': -/Prawdopodobnie wtedy usunie ten. –

2

Jak o:

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

to daje nam:

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 

Funkcją zbioru:

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) 

Wynik:

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 
Powiązane problemy