2015-08-27 16 views
6

chcę mieć flagę przekazany do funkcji, która działa algorytm albo przez Col-row-skanowania lub skanowania:Struktura najpierw uruchomić x vs y najpierw na 2d tablicy

if run-on-x 
    for 1..x 
    for 1..y 
     do something with ary[x][y] 

else 
    for 1..y 
    for 1..x 
     do something with ary[x][y] 

ale nie chcesz powielić wszystkie pętle i logikę.

mam wymyślić to:

let numPx = width * height; 
for (let px = 0; px < numPx; px++) { 
    let [x, y] = yAxis ? [px % width, 0 | px/width] : [0 | px/height, px % height]; 

Ale myślę, że cała matematyka jest dość ciężki, zwłaszcza gdy biegnę go na dość duże tablice.

Czy jest lepszy sposób to zrobić?

+0

Jeśli jest to Java, a następnie, co chce zrobić, to prawdopodobnie strata czasu. kompilacja typu "just-in-time" będzie starała się dalej optymalizować kod bajtowy za każdym razem, gdy jest oceniany (wykonywany). Co więcej, jest dynamiczny: zmieni implementację, jeśli zostanie podjęta inna gałąź. Oznacza to, że może zamieniać pętle w czasie wykonywania, jeśli wydaje się być bardziej optymalnym (i nie łamie żadnych zależności). Próba przechytrzenia kompilatora prawdopodobnie spowoduje "wolniejszy" kod, ponieważ optymalizator zobaczy więcej potencjalnych zależności do zerwania. – StarShine

+0

@StarShine - Dlaczego przyjmujesz założenie, że to java? –

+0

Brak założenia. Tylko komentarz w przypadku, gdy pracujesz w Javie. W pewnym stopniu ten komentarz działa również w JavaScript. We wcześniejszych przeglądarkach wszystkie kompilowały javascript JIT, ale od tego czasu zaczęły generować kod natywny. Jednak możliwe jest, że przyszłe wersje kompilatorów javascript będą miały pewne aspekty jit, takie jak optymalizacja pętli i optymalizacja predykcji gałęzi, ponownie wprowadzane podczas generowania natywnego kodu bajtowego. Zobacz także http: // creativejs.com/2013/06/the-race-for-speed-part-1-the-javascript-engine-family-tree/ – StarShine

Odpowiedz

2

Może po prostu przekazując je jako parametry jak tak ?:

function colRowScan(1stAxis,2ndAxis) 
     for 1.. 1stAxis 
     for 1.. 2ndAxis 
      do something with ary[x][y] 

Nie widząc co „zrobić coś” to ja nie wiem, czy nie ma żadnych nieprzewidzianych powodów nie może działać, ale biorąc pod uwagę to, co napisałeś, powinno załatwić sprawę.

nie jestem do końca pewien, co chce zrobić tutaj:

let numPx = width * height; 
for (let px = 0; px < numPx; px++) { 
    let [x, y] = yAxis ? [px % width, 0 | px/width] : [0 | px/height, px % height]; 
+0

skąd będziesz wiedzieć, że x jest w 1. osi lub 2. osi, gdy próbujesz uzyskać dostęp [x] [y] ? – Somabrata

+0

W obu jego przykładach miał format ary [x] [y], więc nie zmieniłem go, by go zmylić, ale można było wstawić tam również parametry. – IfTrue

+0

Czy mogę to zgadnąć W twoim rozwiązaniu: podczas uzyskiwania dostępu do arii [i] [j] w pętli, pochodzę z pierwszej pętli, a j będzie pochodzić z drugiej pętli? – Somabrata

1
function f(x, y, on_x) { 
    var a, b; 

    if (on_x) { 
     a = x; 
     b = y; 
    } 
    else { 
     a = y; 
     b = x; 
    } 

    for (var ia = 0; ia < a.length; ia++) { 
     for (var ib = 0; ib = b.length; ib++) { 
      // ... 
     } 
    } 
} 
+0

Skąd będziesz wiedzieć, że x jest w a lub b podczas próby uzyskania dostępu [x_i] [y_j] z pętli? może próbować uzyskać dostęp do ary [y_i] [x_j], jeśli y jest w a. – Somabrata

+0

@Somabrata 'a [ia]' lub 'a [ib]' lub odwrotnie: 'b [ia]' lub 'b [ib]'. Zasady alfabetyczne. – Vidul

1

przechowywać dwa zestawy pętli wewnętrznej i zewnętrznej, ale zmienić ciało pętli wewnętrznej do jednego wywołania funkcji . Wtedy nie ma zbyt wiele powielania kodu.

0

Utwórz funkcje pomocnicze dla iteracji wiersza głównego i kolumny głównej, biorąc tablicę i funkcję do zastosowania do elementów tablicy.

var rowMajor = function (a, op) { 
    var maxi = a.length; 
    var maxj = a[0].length; 
    for(var i = 0; i < maxi; ++i) { 
     var row = a[i]; 
     for(var j = 0; j < maxj; ++j) 
      op(row[j],i,j); 
      } 
}; 
var colMajor = function (a, op) { 
    var maxi = a.length; 
    if(maxi === 0) return; 
    var maxj = a[0].length; 
    for(var j = 0; j < maxj; ++j) { 
     for(var i = 0; i < maxi; ++i) { 
      op(a[i][j],i,j); 
     } 
    } 
}; 

// example use (with jQuery) 
var array = [[11,12,13],[21,22,23]]; 
var div = $('<div></div>'); 
var append = function(value) { 
    div.append($('<span></span>').text(value + ' ')); 
}; 

rowMajor(array,append); 
div.append('<br/>'); 
colMajor(array, append); 
$('body').append(div); 
0

W swoim rozwiązaniu

let numPx = width * height; 
for (let px = 0; px < numPx; px++) { 
    let [x, y] = yAxis ? [px % width, 0 | px/width] : [0 | px/height, px % height]; 

Ilość porównania jest numPx razy, podczas gdy wcześniej było to tylko raz, opuścić ciężką matematyki zaangażowany.

Myślę, że prostym i najlepszym rozwiązaniem jest użycie oddzielnej funkcji.

lub można spróbować tego

var a, b, fAry; 

if (run-on-x) { 
    a = x; 
    b = y; 
    fAry = ary; 
} else { 
    a = y; 
    b = x; 
    fAry = transpose of(ary); 
} 

for (var i = 0; i < a; i++) { 
    for (var j = 0; j < b; j++) { 
     do something with fAry[i][j]; 
    } 
} 
1
for 1..x 
    for 1..y { 
     var a = run-on-x ? ary[x][y] : ary[y][x]; 
     do something with a 
    } 
+0

Działa to tylko, jeśli jest to kwadratowa tablica :) –

Powiązane problemy