2015-08-27 4 views
6

Ich möchte ein Flag auf eine Funktion übergeben haben, die einen Algorithmus entweder durch col-Scannen oder Zeilenabtastung ausgeführt wird:Struktur auszuführen x ersten vs y zuerst auf 2D-Array

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] 

aber ich weiß nicht möchte alle Schleifen und Logik duplizieren.

Ich habe mit diesem kommen:

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

Aber ich denke, all die Mathematik ziemlich schwer ist, vor allem, wenn ich es bin mit ziemlich großer Arrays auf.

Gibt es einen besseren Weg, dies zu tun?

+0

versuchen Wenn diese Java ist, dann, was Sie versuchen, ist wahrscheinlich eine Verschwendung von Zeit zu tun. Just-in-Time-Kompilierung wird versuchen, den Byte-Code jedes Mal weiter zu optimieren, wenn er evaluiert (ausgeführt) wird. Darüber hinaus ist es dynamisch: Es wird die Implementierung ändern, wenn eine andere Verzweigung genommen wird. Das bedeutet, dass es die Schleifen zur Laufzeit austauschen kann, wenn es optimaler erscheint (und keine Abhängigkeiten unterbricht). Der Versuch, den Compiler auszutricksen, wird wahrscheinlich zu einem "langsameren" Code führen, da der Optimierer nur noch mehr potentielle Abhängigkeiten sehen kann. – StarShine

+0

@StarShine - Warum machst du die Annahme, dass es Java ist? –

+0

Keine Annahme. Nur ein Kommentar, wenn Sie in Java arbeiten. Bis zu einem gewissen Grad funktioniert dieser Kommentar auch für Javascript. Die früheren Browser haben alle JIT-Compilation von Javascript, aber sind seitdem in Richtung native Code-Generierung bewegt. Es ist jedoch wahrscheinlich, dass zukünftige Entwicklungen von Javascript-Compilern einige Aspekte von jit, wie etwa Schleifenoptimierungen und Verzweigungsvorhersageoptimierung, wieder einbringen werden, wenn auch nativer Byte-Code erzeugt wird. Siehe auch http: // creativejs.com/2013/06/the-race-for-speed-part-1-der-javascript-engine-family-tree/ – StarShine

Antwort

2

Vielleicht indem sie einfach vorbei in als Parameter wie so ?:

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

Ohne zu sehen, was die „etwas tun“ ist, weiß ich nicht, ob es irgendwelche unvorhergesehenen Gründen, warum dies nicht funktionieren könnte, aber gegeben, was Sie gepostet haben, sollte es den Trick tun.

Ich bin nicht ganz sicher, was Sie versuchen, hier zu tun:

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

woher weißt du, dass x in 1.Achse oder 2. achse ist, wenn du versuchst, Zugang zu bekommen ary [x] [y] ? – Somabrata

+0

In beiden Beispielen hatte er das Format ary [x] [y], also änderte ich es nicht, um ihn zu verwirren, aber die Parameter konnten auch dort eingefügt werden. – IfTrue

+0

Kann ich das in Ihrer Lösung erraten: während ich in der Schleife auf ary [i] [j] zugreife, komme ich aus der 1. Schleife und j kommt aus der 2. Schleife? – 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

Woher weißt du, dass x in a oder b ist, wenn du aus der Schleife auf ary [x_i] [y_j] zugreifst? Es kann versuchen, auf ary [y_i] [x_j] zuzugreifen, wenn y in a ist. – Somabrata

+0

@Somabrata 'a [ia]' oder 'a [ib]' oder das Gegenteil: 'b [ia]' oder 'b [ib]'. Alphabetische Prinzipien. – Vidul

1

Halten Sie die zwei Sätze von inneren und äußeren Schleifen, sondern den Körper der inneren Schleife zu einem einzigen Funktionsaufruf ändern . Dann gibt es nicht viel Codeverdopplung.

0

Erstellen Sie Hilfsfunktionen für die Haupt-Iteration der Zeilenhaupt- und -spalte, indem Sie das Array und eine Funktion für die Array-Elemente übernehmen.

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

In Ihrer Lösung

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

Anzahl des Vergleichs ist numPx mal während es früher nur einmal war, ging es um die schwere Mathe auslassen.

Ich denke, die einfache und beste Lösung ist es, eine separate Funktion zu verwenden.

OR können Sie diese

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

Das funktioniert nur, wenn es ein quadratisches Array ist :) –