2009-04-24 9 views
1

Let sagen, dass ich diese Funktion hätte:C# Array-Funktion Argument übergibt eine Dimension

void int Calculate(double[] array) {} 

Und in meinem Haupt habe ich dieses Array:

double[,] myArray = new double[3,3]; 

Wie kann ich berechnen nennen (...) ?

Ich versuche (das Kompilieren nicht wichtig):

double[] mySingleArray = myArray[0]; 

Was ich vermeiden wollen unnötige Schleife ist (for).

Ich erkläre ein reguläres Array, aber wenn ein gezacktes Array oder eine andere Art von Array besser funktioniert, ist es in Ordnung für mich.

Ich verwende C# 3.5

+0

Ich bin gespannt, was Ihre Berechnungsmethode tut. Ich wette, wir könnten es als Lambda-Ausdruck verwenden, indem Sie eine IEnumerable-Aggregat-Erweiterung verwenden. –

Antwort

6

Lassen Sie uns zunächst erklären, um Ihre berechnen() -Methode wie folgt aus:

int Calculate(IEnumerable<double> doubles) 

Keine Sorge, Sie noch ein Array an diesem Code weitergeben können. Möglicherweise benötigen Sie auch IList<double>, aber 9 von 10 Fällen ist IEnumerable gut genug. Die Hauptsache ist, dass wir das yield Schlüsselwort verwenden läßt Ihre Array auf eine effiziente Art und Weise zu zerschneiden:

public static IEnumerable<T> Slice(this T[,] values) 
{ 
    return Slice(values, 0, 0); 
} 

public static IEnumerable<T> Slice(this T[,] values, int index) 
{ 
    return Slice(values, 0, index); 
} 

public static IEnumerable<T> Slice(this T[,] values, int dimension, int index) 
{ 
    int length = values.GetUpperBound(dimension); 
    int[] point = new int[values.Rank]; 
    point[dimension] = index; 
    dimension = 1 - dimension;// only works for rank == 2 
    for (int i = 0; i < length; i++) 
    { 
     point[dimension] = i; 
     yield return (T)values.GetValue(point); 
    } 
} 

Es braucht noch etwas Arbeit, weil es nur mit Rang 2 Arrays funktioniert, aber es sollte in Ordnung sein das Beispiel, das du gepostet hast.

Jetzt können Sie Ihre berechnen Funktion wie folgt aufrufen:

Calculate(myArray.Slice(0)); 

Beachten Sie, dass aufgrund der Art und Weise IEnumerable und die Ausbeute Erklärung der im Code für Schleife arbeiten ich gepostet im Wesentlichen frei. Sie wird nicht ausgeführt, bis Sie die Elemente in Ihrer Calculate-Methode tatsächlich iterieren, und selbst dort wird "Just-in-Time" ausgeführt, sodass der gesamte Algorithmus O (n) bleibt.

Es wird noch interessanter, wenn Sie teilen, was Ihre Calculate-Methode macht. Sie können es möglicherweise als einfachen Aggregat + Lambda-Ausdruck ausdrücken. Zum Beispiel, sagen wir mal, Ihre berechnen Methode die Anzahl der Elemente> 5 zurückgegeben:

myArray.Slice(0).Count(x => x > 5); 

Oder sagen, es summiert alle Elemente:

myArray.Slice().Sum(); 
+0

Dies ist sicherlich eine bessere Lösung, wenn das Problem ein echtes mehrdimensionales Array und kein gezacktes Array erfordert. – mquander

4

Ein gezackten Array funktioniert so, wie Sie wollen:

double[][] jaggedArray = new double[][100]; 
for (int i = 0; i < jaggedArray.Length; ++i) 
    jaggedArray[i] = new double[100]; 

myFunction(jaggedArray[0]); 

Sie können auf diese Weise für jedes Array unterschiedliche Größen haben.

+0

Gibt es eine Möglichkeit, mein gezacktes Array ohne ein for zu initialisieren? Ich meine etwas wie: double [] [] jaggedArray = new double [100] [100]; ? – Melursus

+0

Nein, im Wesentlichen erstellen Sie ein Array von 'double []' - Objekten. Diese Objekte haben keinerlei Bezug zum ursprünglichen Array. –

0

Ein gezacktes Array lässt Sie das erste Array aufteilen!

0

Die Scheibe() -Methode oben angegebenen erhalten Sie einen einzigen Zeile aus Ihrem Array, die mit dem in Ihrer Frage angegebenen Beispiel übereinstimmt.

Wenn Sie jedoch ein eindimensionales Array mögen, die all die Elemente in der rechteckigen Anordnung enthält, können Sie so etwas wie diese, die auch O (n).

public static T[] Flatten<T>(this T[,] array) 
    where T : struct 
{  
    int size = Marshal.SizeOf(array[0, 0]); 
    int totalSize = Buffer.ByteLength(array); 
    T[] result = new T[totalSize/size]; 
    Buffer.BlockCopy(array, 0, result, 0, totalSize); 
    return result;  
} 
Verwandte Themen