在 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 另外我不确定是否有任何方法可以在 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 方法的主要内容,如果未能解决你的问题,请参考以下文章