2008-10-13 4 views
5

Wie kann ich die Ruby-Methode "Flatten" Ruby Method in C#. Diese Methode flacht ein gezacktes Array zu einem eindimensionalen Array ab.Flatten Rubin Methode in C#

Zum Beispiel:

s = [ 1, 2, 3 ]   #=> [1, 2, 3] 
t = [ 4, 5, 6, [7, 8] ] #=> [4, 5, 6, [7, 8]] 
a = [ s, t, 9, 10 ]  #=> [[1, 2, 3], [4, 5, 6, [7, 8]], 9, 10] 
a.flatten     #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10 
+0

Sie haben es hier mit einem gezackten Array (Array) zu tun, nicht mit mehrdimensionalen Arrays. – leppie

+0

Prost, mein Fehler - sortiert. – chrisntr

Antwort

12

rekursive Lösung:

IEnumerable Flatten(IEnumerable array) 
{ 
    foreach(var item in array) 
    { 
     if(item is IEnumerable) 
     { 
      foreach(var subitem in Flatten((IEnumerable)item)) 
      { 
       yield return subitem; 
      } 
     } 
     else 
     { 
      yield return item; 
     } 
    } 
} 

EDIT 1:

Jon in den Kommentaren erklärt, warum es nicht eine generische Methode sein kann, einen Blick darauf werfen!

EDIT 2:

Matt vorgeschlagen es eine Erweiterungsmethode macht. Hier gehen Sie, ersetzen Sie einfach die erste Zeile mit:

public static IEnumerable Flatten(this IEnumerable array) 

und Sie können es wie folgt verwenden:

foreach(var item in myArray.Flatten()) { ... } 
+1

Mein erster Gedanke war: "Warum ist es nicht generisch?" - aber natürlich kann es nicht sein, denn nur sehr selten ist eine iterierbare Version von T auch ein T. (zB IEnumerable ist immer noch ein Objekt, aber IEnumerable ist kein String.) Es lohnt sich, dies zu klären in der Antwort. –

+0

Auch ich bin mir nicht sicher, ob es eine Möglichkeit gibt, ein stark typisiertes zackiges Array in C# zu deklarieren, gibt es? Es muss object [] sein, was bedeutet, dass IEnumerable ein vernünftiger Parametertyp für diese Methode ist. –

+0

Matt: Nicht sicher, was Sie mit "strong-typed zerlumpten Array" aber int [] [] und int [,] (für gezackte und rechteckige Arrays von Ints jeweils) sind in Ordnung. –

2

ich in einem Kommentar geantwortet haben würde, aber ich brauche mehr als 300 Zeichen.

@ Alexanders Lösung ist genial, aber es läuft auf ein Problem mit Arrays von Strings. Da string IEnumerable implementiert, denke ich, dass jedes Zeichen in jeder Zeichenfolge zurückgegeben wird. Sie können einen generischen Parameter verwenden, um ihm zu sagen, welche Art von Sache, die Sie in diesen Fällen zurückgekehrt sein hoffen, z.B .:

public static IEnumerable Flatten<T>(IEnumerable e) 
{ 
    if (e == null) yield break; 
    foreach (var item in e) 
    { 
     if (item is T) 
      yield return (T)item; 
     else if (item is IEnumerable) 
     { 
      foreach (var subitem in Flatten<T>((IEnumerable)item)) 
       yield return subitem; 
     } 
     else 
      yield return item; 
    } 
} 
1

Könnten Sie nicht nur IEnumerable # Select verwenden?