Linq投影的扁平表到父和子对象图

本文关键字:对象图 投影 Linq | 更新日期: 2023-09-27 18:09:58

我有一个包含扁平父子关系的可枚举列表:

ParentGuid1, ParentName1, ChildGuid1, ChildName1
ParentGuid1, ParentName1, ChildGuid2, ChildName2
ParentGuid2, ParentName2, ChildGuid3, ChildName3
ParentGuid2, ParentName2, ChildGuid4, ChildName4

我已经定义了一个子类和一个父类,其中包括一个名为Children的List<Child>属性。

我可以使用linq来创建一个对象图,每个唯一的ParentGuid都有一个Parent类的实例,引用一个由与该父类关联的子类填充的列表。

类似这样的内容(注意,这段代码不能编译):

myFlattenedHierarchy.Select(p => new Parent
   {Guid = p.ParentGuid, 
    Name = p.ParentName, 
    Children = myFlattenedHierarchy.Where(c => c.ParentGuid == p.ParentGuid).Select(c => new Child{Guid = c.ChildGuid, Name = c.ChildName})
   });

Linq投影的扁平表到父和子对象图

myFlattenedHierarchy.Select(p => new Parent
   {Guid = p.ParentGuid, 
    Name = p.ParentName, 
    Children = myFlattenedHierarchy.Where(c => c.ParentGuid == p.ParentGuid).Select(c => new Child{Guid = c.ChildGuid, Name = c.ChildName})
   });

你应该能够做到这一点,但Children不能是一个列表,它必须是IEnumerable

这是linq之前的方法,使用一个简单的循环。

Dictionary<Guid, Parent> parents = new Dictionary<Guid, Parent>();
foreach(RowType row in myFlattenedHierarchy) //just enumerate once
{
  if (!parents.ContainsKey(row.ParentGuid)
  {
    Parent newParent = new Parent(row);
    parents[row.ParentGuid] = newParent;
  }
  Child newChild = new Child(row);
  Parent theParent = parents[row.ParentGuid];
  theParent.Children.Add(newChild);  
}
List<Parent> result = parents.Values.ToList();

或者您可以使用GroupBy来获得类似的结果。

from row in myFlattenedHierarchy
group row by row.ParentGuid into g
select new Parent()
{
  Guid = g.Key,
  Name = g.First().ParentName,
  Children =
  (
    from childRow in g
    select new Child()
    {
      Guid = childrow.ChildGuid,
      Name = childrow.ChildName
    }
  ).ToList()
}

这是一个比较容易维护的问题。无论如何,都不要在循环/查询中重新枚举myflatedhierarchy。

我相信你可以使用GroupBy()(完全披露:未编译):

myFlattenedHierarchy.GroupBy(row => row.ParentGuid)
    .Select(group => new Parent
        {
            Guid = group.Key.ParentGuid,
            Name = group.Key.ParentName,
            Children = myFlattenedHierarchy.Where(c => c.ParentGuid == group.Key.ParentGuid)
                .Select(c => new Child{ Guid = c.ChildGuid, Name = c.ChildName })
                .ToList()
        });

如果在平面集合中有一个循环,则需要处理递归性和无限递归性。Linq不能用于完整的问题,但可以帮助返回特定节点的子节点。

这应该工作,非常类似于大卫B的第二个例子,但我不能得到他的工作没有一点修复(按多列分组),所以我在这里添加了它的记录。

from row in myFlattenedHierarchy
group row by new { row.ParentGuid, row.ParentName } into g
select new Parent()
{
  Guid = g.Key.ParentGuid,
  Name = g.Key.ParentName,
  Children =
  (
    from childRow in g
    select new Child()
    {
      Guid = childRow.ChildGuid,
      Name = childRow.ChildName
    }
  ).ToList()
};