假设我有这个简单的结构
class FooDefinition
{
public FooDefinition Parent { get; set; }
}
class Foo
{
public FooDefinition Definition { get; set; }
}
class Bar
{
public ICollection<Foo> Foos { get; set; }
}
Bar
的{{1}}列表可以很简单(没有父/子关系)或只嵌套一个级别(即父Foos
有多个孩子Foo
})。从这里可以看出,关系是在Foos
中指定的,而不是FooDefinition
。
我需要做的是生成一个按此层次结构正确分组的Foo itself
列表。请考虑以下源数据:
Foos
我想和他们的孩子一起收集顶级物品。一个适当的数据结构可能是var simpleDefinition = new FooDefinition();
var parentDefinition = new FooDefinition();
var childDefinition = new FooDefinition { Parent = parentDefinition };
var bar = new Bar { Foos = new[]
{
new Foo { Definition = simpleDefinition },
new Foo { Definition = parentDefinition },
new Foo { Definition = childDefinition }
}};
。
结果如下:
当然,我想用纯功能的Linq查询来做到这一点。我做了很多这些,但我的大脑今天似乎停滞不前。
答案 0 :(得分:3)
bar.Foos.Where(x => x.Definition.Parent == null)
.Select(x => Tuple.Create(x,
bar.Foos.Where(c => c.Definition
.Parent == x.Definition
)));
这将返回IEnumerable<Tuple<Foo, IEnumerable<Foo>>>
,其中Item2
的{{1}}包含Tuple
中父项的子项。对于您的示例,这将返回两个元组:
Item1
和Item1 = simpleDefinition
包含空的可枚举Item2
和Item1 = parentDefinition
包含一个包含Item2
可能有更优雅或更快的方式,但我无法想出来......
哦,好吧,我对此我的评论有点矛盾,但是childDefinition
有可能 - 至少差不多:
GroupBy
这将返回bar.Foos.Where(x => x.Definition.Parent == null)
.GroupBy(x => x,
x => bar.Foos.Where(c => c.Definition.Parent == x.Definition));
。
更新:
我想知道,如果您想要的解决方案是可能的。
是的,它是:
IEnumerable<IGrouping<Foo, IEnumerable<Foo>>>
但我真的不想知道大O 这个并且它真的不应该被使用; - )
答案 1 :(得分:0)
如果您添加了一个类和一个方法,则可以转到IEnumerable<IGrouping<Foo,Foo>>
。
class FooRelation{
public Foo Parent {get; set;}
public Foo Child {get; set;}
}
static IEnumerable<FooRelation> GetChildren(Bar source, Foo parent){
var children = source.Foos.Where(c => c.Definition.Parent == parent.Definition);
if(children.Any())
return children.Select(c => new FooRelation{Parent = parent, Child = c});
return new FooRelation[]{new FooRelation{Parent = parent}};
}
您甚至可以将该静态方法折叠到此查询中......但它会变得混乱:
var r = bar.Foos.Where(x => x.Definition.Parent == null)
.SelectMany(x => GetChildren(bar, x))
.GroupBy(fr => fr.Parent, fr => fr.Child);