Also stellt sich heraus , dass alle Arrays nicht gleich sind. Mehrdimensionale Arrays können Untergrenzen ungleich Null haben. Siehe beispielsweise Excel PIAs Range.Value-Eigenschaft object[,] rectData = myRange.Value;
Ich muss diese Daten in ein gezacktes Array konvertieren. Mein erster Versuch unten riecht nach Komplexität. Irgendwelche Vorschläge, um es zu optimieren? Es muss den allgemeinen Fall behandeln, in dem untere Grenzen nicht Null sein dürfen.
Ich habe diese Ex-Methode:
%Vor%Verwendet wie folgt:
%Vor%Neugierig, wenn Buffer.BlockCopy () funktioniert oder schneller ist?
Edit: AsJagged muss Referenztypen behandeln.
Bearbeiten: Fehler in AsJagged () gefunden. Hinzugefügt int l
; und col1 + width
zur inneren Schleife hinzugefügt.
Ein Ausblick Vorbehalte / Annahmen:
int
als Datentyp zu verwenden (oder zumindest in Ordnung zu sein, wenn Sie Buffer.BlockCopy
verwenden, was bedeuten würde, dass Sie im Allgemeinen mit primitiven Typen leben können). Nachdem dies gesagt wurde, ist die folgende Implementierung (die für einen bestimmten primitiven Typ (hier int
) spezialisiert werden muss, weil fixed
verwendet wird, etwa 10 mal schneller als der Ansatz mit der inneren Schleife:
Verwenden Sie den folgenden "Testcode":
%Vor% Wo AsJagged
(der erste Fall) Ihre ursprüngliche Funktion ist, bekomme ich folgende Ausgabe:
Es gibt also einen schnelleren Weg, aber abhängig von der Größe der Testdaten, der Anzahl, wie oft Sie diesen Vorgang tatsächlich durchführen, und Ihrer Bereitschaft, unsicheren und P / Invoke-Code zuzulassen werde es wahrscheinlich nicht brauchen .
Nachdem wir das gesagt hatten, benutzten wir große Matrizen von double
(sagen wir 7000x10000 Elemente), wo es tatsächlich einen großen Unterschied machte.
Update: Informationen zur Verwendung von Buffer.BlockCopy
Ich könnte einige Marshal
oder andere Tricks übersehen, aber ich denke nicht, dass Buffer.BlockCopy
hier möglich ist. Dies liegt an der Tatsache, dass es sowohl das Quell- als auch das Zielarray benötigt, um ein Array
zu sein.
In unserem Beispiel ist das Ziel ein Array (z. B. int[] temp = ...
), die Quelle jedoch nicht. Während wir "wissen", dass für zweidimensionale Arrays primitiver Typen das Layout so ist, dass jede "Zeile" (dh erste Dimension) ein Array des Typs im Speicher ist, gibt es keinen sicheren Weg (wie in unsafe
) Holen Sie sich dieses Array ohne den Aufwand, es zuerst zu kopieren. Also müssen wir im Grunde eine Funktion verwenden, die sich nur mit Speicher beschäftigt und sich nicht um den tatsächlichen Inhalt kümmert - wie MoveMemory
. Übrigens, die interne Implementierung von Buffer.BlockCopy
macht etwas ähnliches.
Ihre Komplexität ist O (N * M) N - Anzahl der Zeilen, M - Anzahl der Spalten. Das ist das Beste, was man beim Kopieren von N * M-Werten bekommen kann ...
Buffer.BlockCopy ist vielleicht schneller als Ihre innere for-Schleife, aber ich wäre nicht überrascht, wenn der Compiler weiß, wie er mit diesem Code richtig umgehen soll und Sie keine weitere Geschwindigkeit gewinnen werden. Sie sollten es testen, um sicher zu gehen.
Sie können möglicherweise eine bessere Leistung erzielen , indem Sie die Daten überhaupt nicht kopieren (mit dem potenziellen Aufwand für etwas langsamere Suchvorgänge). Wenn Sie eine Klasse 'array row' erstellen, die Ihre rect- und eine Zeilennummer enthält und einen Indexer bereitstellt, der auf die richtige Spalte zugreift, können Sie ein Array solcher Zeilen erstellen und den gesamten Kopiervorgang speichern.
Die Komplexität der Erstellung eines solchen Arrays von 'Array-Zeilen' ist O (N).
EDIT: Eine ArrayRow Klasse, nur weil es mich nervt ...
Das ArrayRow könnte in etwa so aussehen:
%Vor%Sie erstellen jetzt ein Array von ArrayRows, Sie kopieren überhaupt nichts, und das Optimierungsprogramm hat eine gute Chance, den Zugriff auf eine ganze Zeile nacheinander zu optimieren.
Tags und Links arrays c# multidimensional-array jagged-arrays