我有一个 IEnumerable<object>
,其中可能包含一些嵌套集合。例如,我的起点可能看起来像这样:
[ "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));
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<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);
这个方法有点不太好,但是只适用于一个层级:
a.SelectMany(t =>
(t is IEnumerable<object>)
? (IEnumerable<object>)t
: new object[] {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;
}
}
"foo"
是一个字符串
,它实现了IEnumerable<char>
,听起来你不想要的是['f', 'o', 'o', ...]
这种形式。 - Joel Rondeau