在 C# 中展平 Ruby 方法

Posted

技术标签:

【中文标题】在 C# 中展平 Ruby 方法【英文标题】:Flatten Ruby method in C# 【发布时间】:2010-09-16 20:38:41 【问题描述】:

如何在 C# 中执行 Ruby 方法 "Flatten" Ruby Method。该方法将锯齿状数组展平为一维数组。

例如:

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

【问题讨论】:

您在这里处理的是锯齿状(数组的数组)数组,而不是多维数组。 【参考方案1】:

递归解:

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在cmets中解释了为什么不能是泛型方法,看看吧!

编辑 2:

Matt 建议将其设为扩展方法。在这里,只需将第一行替换为:

public static IEnumerable Flatten(this IEnumerable array)

你可以这样使用它:

foreach(var item in myArray.Flatten())  ... 

【讨论】:

我最初的想法是“为什么它不是通用的?” - 但当然不可能,因为 T 的可迭代版本也很少是 T。(例如 IEnumerable 仍然是一个对象,但 IEnumerable 不是字符串。)它可能值得在答案中澄清这一点。 另外我不确定是否有任何方法可以在 C# 中声明一个强类型的不规则数组?它必须是 object[],这意味着 IEnumerable 是该方法的合理参数类型。 Matt:不确定您所说的“强类型不规则数组”是什么意思,但 int[][] 和 int[,](分别用于整数的锯齿和矩形数组)很好。 @Matt:确实,这正是我的想法。 @Jon:我总是尝试首先使用最简单的方法。显然它也是最通用的:int[][] 和 int[,] 都是 IEnumerables。如果 flatten() 的调用者事先知道类型,她总是可以转换为它们。【参考方案2】:

我会在评论中回复,但我需要超过 300 个字符。

@Alexander 的解决方案很棒,但它遇到了字符串数组的问题。由于字符串实现了 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;
    

【讨论】:

【参考方案3】:

你不能只使用 IEnumerable#SelectMany 吗?

【讨论】:

【参考方案4】:

我也同意 SelectMany 这样做。

var s = new[]  1, 2, 3 ;
var t = new[]  4, 5, 6 ;
var a = new[]  s, t, new[] 7, 8 ;

a.SelectMany(e => e); 
// IEnumerable<int> 1,2,3,4,5,6,7,8

我对数组进行了标准化。 s 和 t 是 int 数组。 a 是一个数组数组。 你没有混合数组与 int 和数组,就像你可以在 ruby​​ 中那样。

但反之亦然。 flatten 是我在 C# 中寻找 SelectMany 的 ruby​​ 等价物

【讨论】:

以上是关于在 C# 中展平 Ruby 方法的主要内容,如果未能解决你的问题,请参考以下文章

C#使用列表属性展平对象列表[重复]

在Ruby中递归地展平数组[重复]

ruby 展平整数数组

ruby 展平任意嵌套的数组

在标量上下文中展平 Perl 数组的方法

c#圆形展平数组