C# 展平可能包含阵列的对象阵列

C# 展平可能包含阵列的对象阵列,c#,arrays,linq,C#,Arrays,Linq,我有一个IEnumerable,它可能包含也可能不包含一些嵌套集合。例如,我的起点可能如下所示: [ "foo", 2, [1, 2, 3, 4], "bar" ] 我想把它展平到: [ "foo", 2, 1, 2, 3, 4, "bar" ] 我认为在这里可以使用SelectMany,但无法找到正确的组合。我可以强行使用它,但我认为应该有一个更优雅的解决方案; IEnumerable<object> source = new object[] { "test", 1, new

我有一个
IEnumerable
,它可能包含也可能不包含一些嵌套集合。例如,我的起点可能如下所示:

[ "foo", 2, [1, 2, 3, 4], "bar" ]
我想把它展平到:

[ "foo", 2, 1, 2, 3, 4, "bar" ]
我认为在这里可以使用
SelectMany
,但无法找到正确的组合。我可以强行使用它,但我认为应该有一个更优雅的解决方案;
IEnumerable<object> source = new object[] { "test", 1, new[] { 1, 2, 3 }, "test" };

var result = source .SelectMany(x => x is Array ? ((IEnumerable)x).Cast<object>() : Enumerable.Repeat(x, 1));
var result=source.SelectMany(x=>x是数组?((IEnumerable)x).Cast():Enumerable.Repeat(x,1)); 要使其与嵌套数组一起工作,请使lambda递归:

IEnumerable<object> source = new object[] { "test", 1, new object[] { 1, 2, new [] { "nested", "nested2" } }, "test" };

Func<IEnumerable<object>, IEnumerable<object>> flatten = null;
flatten = s => s.SelectMany(x => x is Array ? flatten(((IEnumerable)x).Cast<object>()) : Enumerable.Repeat(x, 1));

var result = flatten(source);
IEnumerable source=new object[]{“test”,1,new object[]{1,2,new[]{“nested”,“nested2”},“test”};
Func flatte=null;
展平=s=>s.SelectMany(x=>x是数组?展平(((IEnumerable)x).Cast()):可枚举。重复(x,1));
var结果=扁平化(源);

这有点恶心,但很管用。。假设只有一个级别:

a.SelectMany(t => 
     (t is IEnumerable<object>)
      ? (IEnumerable<object>)t 
      : new object[] {t})
a.SelectMany(t=>
(t是可数的)
?(IEnumerable)t
:新对象[]{t})
我怀疑最“优雅”的解决方案实际上是编写一个扩展

public static IEnumerable<T> Flatten<T>(this IEnumerable<T> @this) {
    foreach (var item in @this) {
        if (item is IEnumerable<T>) {
            foreach (var subitem in Flatten((IEnumerable<T>)item)) {
                yield return subitem;
            }
        }
        else yield return item;
    }
}
公共静态IEnumerable展平(this IEnumerable@this){
foreach(@this中的变量项){
如果(项是IEnumerable){
foreach(展平中的var子项((IEnumerable)项)){
收益回报子项;
}
}
其他收益返回项目;
}
}

略短的递归备选方案:

IEnumerable<object> source = new object[] { "test", 1, new object[] { 1, 2, new [] { "nested", "nested2" } }, "test" };

Func<IEnumerable<object>, IEnumerable<object>> flatten = null;
flatten = s => s == null ? null : s.SelectMany(x => 
   flatten(x as IEnumerable<object>) ?? new [] { x }
);
var result = flatten(source);
IEnumerable source=new object[]{“test”,1,new object[]{1,2,new[]{“nested”,“nested2”},“test”};
Func flatte=null;
展平=s=>s==null?null:s.SelectMany(x=>
展平(x为IEnumerable)??新[]{x}
);
var结果=扁平化(源);

你看到了吗:@MikeCheel:事实上我看到了,但那不是一回事。那是一张名单。这是一个对象列表,其中一些可能是列表。我想同时选择不是列表的对象和每个列表的内容。您的嵌套总是两层深还是可以有更深层的嵌套数组?@MikeCheel:这不相关。列表中可以是什么类型的列表类型对象?我问这个问题是因为
“foo”
是一个
字符串,它实现了
IEnumerable
,而且听起来好像你不想要
['f','o','o',…]
。它不会处理嵌套数组。@SLaks我用递归解决方案更新了我的答案。这很聪明!不过,为了清晰起见,我还是喜欢我的;在某一点之外,简洁和清晰可能是相互排斥的。