编程语言
首页 > 编程语言> > c# – Linq-to-objects:从平面源创建两级层次结构

c# – Linq-to-objects:从平面源创建两级层次结构

作者:互联网

假设我有这个简单的结构

class FooDefinition
{
    public FooDefinition Parent { get; set; }
}

class Foo
{
    public FooDefinition Definition { get; set; }
}

class Bar
{
    public ICollection<Foo> Foos { get; set; }
}

Bar有一个Foos列表,它可以很简单(没有父/子关系)或只嵌套一个级别(即父Foo有很多子Foos).从这里可以看出,关系是在FooDefinition中指定的,而不是Foo本身.

我需要做的是生成一个按此层次结构正确分组的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 }
                           }};

我想和他们的孩子一起收集顶级物品.适当的数据结构可能是IEnumerable< IGrouping< Foo,Foo>>.

结果如下:

>第1项(简单)
>第2项(父母)

>第3项(儿童)

当然,我想用一个纯功能的Linq查询来做到这一点.我做了很多这些,但我的大脑今天似乎陷入困境.

解决方法:

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>>>,其中Tuple的Item2包含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>>>.

更新:
我想知道,如果你想要的解决方案是可能的.
是的:

bar.Foos.Where(x => x.Definition.Parent != null)
        .GroupBy(x => bar.Foos.Where(y => y.Definition == x.Definition.Parent)
                              .Single(),
                 x => x)
        .Union(bar.Foos.Where(x => x.Definition.Parent == null && 
                                   !bar.Foos.Any(c => c.Definition.Parent == 
                                                      x.Definition))
                       .GroupBy(x => x, x => (Foo)null));

但我真的不想知道这个的大O,它真的不应该被使用;-)

标签:c,linq-to-objects
来源: https://codeday.me/bug/20190630/1338736.html