2008-10-13 39 views
5

如何在C#中执行Ruby方法"Flatten" Ruby Method。此方法将锯齿状阵列变平成一维阵列。在C#中拼合Ruby方法#

例如:

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

您正在处理锯齿(数组数组)阵列,而不是多维数组。 – leppie 2008-10-13 09:21:43

+0

干杯,我的错误 - 排序。 – chrisntr 2008-10-13 09:27:47

回答

12

递归解决方案:

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

编辑1:

Jon解释了为什么评论它不可能是一个通用的方法,一起来看看!

编辑2:

Matt建议使得它的扩展方法。在这里,你走了,只需更换的第一行:

public static IEnumerable Flatten(this IEnumerable array) 

,你可以使用它像这样:

foreach(var item in myArray.Flatten()) { ... } 
2

我会在评论已作出回应,但我需要超过300个字符。

@亚历山大的解决方案很棒,但它遇到了字符串数组的问题。由于字符串实现IEnumerable,我认为它将最终返回每个字符串中的每个字符。您可以使用泛型参数来告诉它你希望在这些情况下又回到什么样的事情,例如:

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

你不能只使用IEnumerable的#的SelectMany?