从子集合中获取具有层次结构的父集合



我遇到了问题。

我有一个孙子集合,我想使用 LINQ 将其转换为祖父对象的集合。子对象具有父对象的导航属性。我尝试过按祖父母名字分组,但后来我被一个字符串卡住了。

我的祖父母班级看起来像这样:

祖父类

 public class GrandParentBLL
{
    public GrandParentBLL()
    {
        Parents= new List<Parent>();
    }
    public int ID { get; set; }
    public int Number { get; set; }
    public string Name { get; set; }
    public ICollection<ParentBLL> Parents{ get; set; }
}

儿童班:

Child class
 public class ParentBLL
{
    public ParentBLL()
    {
        Children= new List<Child>();
    }
    public int ID { get; set; }
    public int Number { get; set; }
    public string Name { get; set; }
    public GrandParentBLL GrandParent { get; set; }
    public ICollection<ChildBLL> Children { get; set; }
}

孙子班:

public class ChildBLL
{
    public ChildBLL()
    {
    }
    public int ID { get; set; }
    public int Number { get; set; }
    public string Name { get; set; }
    public ParentBLL Parent{ get; set; }
}

现在我得到了一个孙子对象列表,其中每个对象可以有不同的父项或祖父项。我可以使用导航属性访问父级。我想获取祖父对象的列表,其中包含每个祖父项的相应子集合。

我尝试了以下方法:

var grandparents = Children.GroupBy(x => x.Parent.GrandParent).Select(d=>d.Key).ToList();

但是后来我为孙子收藏中的每个对象都得到了一个祖父对象,尽管只有 2 个不同的祖父母。

如果要获取唯一的祖父实体,则查询应为

 var grandparents = grandChildren
                    .Select(c => c.Parent) // --> get all the grand children's parents
                    .Select(p => p.GrandParent) // --> get all the GrandParents from each of the Parents above
                    .Distinct();

更新:因此,如果父对象不保存子集合,请根据您的评论以及接受的答案。以下是为父对象添加水处理的一种方法:

IEnumerable<ParentBLL> parents = grandChildren
                       .Select(gc => gc.Parent)
                       .Distinct()
                       .Pipe(p => p.GrandChildren = grandChildren.Where(gc => gc.Parent.ID == p.ID).ToList());
IEnumerable<GrandParentBLL> grandparents = parents
                            .Select(p => p.GrandParent).Distinct()
                            .Pipe( gp => gp.Parents = parents.Where(p => p.GrandParent.ID == gp.ID).ToList());

该解决方案使用 .Pipe ,它"对源序列中的每个元素执行给定的操作并生成它"。这是来自MoreLinq的扩展方法。因此,您需要添加对此包的引用。

容易

从您的示例中不清楚每个类是否都有自己的直系子级集合。如果他们这样做了,答案很简单:

Dictionary<GrandParent,List<Child>> results = grandparents.ToDictionary
(
    g => g,
    g => g.Parents.SelectMany( p => p.Children ).ToList()
);

不那么容易

如果父母不了解他们的孩子,

只有孩子知道他们的直系父母,那么还有更多的工作,我将分三个步骤带你完成:

第 1 步。首先获取一个可以重用的父母和祖父母的枚举器:

var parents = children.Select( c => c.Parent ).Distinct();
var grandParents = parents
    .Select( p => p.GrandParent )
    .Distinct();

第 2 步。现在修改代码以将grandParents更改为Dictionary<GrandParent,List<Parent>>

var children = new List<ChildBLL>();
var parents = children.Select( c => c.Parent ).Distinct();
var grandParents = parents
    .Select( p => p.GrandParent )
    .Distinct()
    .ToDictionary
    ( 
        g => g, 
        g => parents.Where( p => p.GrandParent == g )
    );

第 3 步。添加代码以将Dictionary<GrandParent,List<Parent>>转换为Dictionary<Grandparent,List<Child>>

var parents = children.Select( c => c.Parent ).Distinct();
var grandParents = parents
    .Select( p => p.GrandParent )
    .Distinct()
    .ToDictionary
    ( 
        g => g, 
        g => parents.Where( p => p.GrandParent == g )
    )
    .ToDictionary
    (
        pair => pair.Key,
        pair => pair.Value.SelectMany
        ( 
            p => children.Where( c => c.Parent == p ) 
        )
    );

完成后,您将拥有一个字典,其中键是祖父级,值是其孙子级的List<Children>

最新更新