2008-10-13 17 views
5

¿Cómo puedo hacer el método Ruby "Flatten" Ruby Method en C#. Este método aplana una matriz dentada en una matriz de una sola dimensión.Método Flatten Ruby en C#

Por ejemplo:

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

Se trata de matrices irregulares (matriz de matrices) aquí, y no multidimensionales. – leppie

+0

Saludos, mi error - ordenados. – chrisntr

Respuesta

12

solución recursiva:

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 explica en los comentarios por lo que no puede ser un método genérico, echar un vistazo!

EDIT 2:

Matt sugirió por lo que es un método de extensión. Aquí tiene, basta con sustituir la primera línea con:

public static IEnumerable Flatten(this IEnumerable array) 

y se puede utilizar de esta manera:

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

Mi pensamiento inicial fue "¿Por qué no es genérico?" - pero por supuesto no puede ser porque solo muy raramente es una versión iterable de T también una T. (por ejemplo, IEnumerable sigue siendo un objeto, pero IEnumerable no es una cadena.) Puede valer la pena aclarar esto en la respuesta. –

+0

Además, no estoy seguro de que haya alguna forma de declarar una matriz fragmentada fuertemente tipada en C# ¿hay alguna? Tiene que ser objeto [], lo que significa que IEnumerable es un tipo de parámetro razonable para este método. –

+0

Matt: No estoy seguro de lo que quiere decir con "matriz irregular fuertemente tipada" pero int [] [] e int [,] (para arreglos irregulares y dentados de ints, respectivamente) están bien. –

2

yo hubiera respondido en un comentario, pero necesito más de 300 caracteres.

@ La solución de Alexander es increíble, pero tiene un problema con las matrices de cadenas. Como string implementa IEnumerable, creo que terminará devolviendo cada carácter en cada cadena. Puede utilizar un parámetro genérico para decirle qué tipo de cosas que usted está esperando haber vuelto en estos casos, por ejemplo .:

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

¿No podrías utilizar IEnumerable # SelectMany?