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我用递归解决方案更新了我的答案。这很聪明!不过,为了清晰起见,我还是喜欢我的;在某一点之外,简洁和清晰可能是相互排斥的。