2011-09-29 50 views
6

我有一个包含一个扁平的父 - 子关系的枚举列表:LINQ的投影到父和子对象图

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

我已经定义了一个子类和一个父类,其包括List<Child>属性称为儿童。

我可以使用linq在对象图上创建每个唯一ParentGuid的父类的一个实例,引用与该父级关联的子级填充的List。

沿着这条的线

东西(注意,此代码不编译):

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}) 
    }); 
+0

该图只有2层深,即没有周期的“Parent 1- * Child”?或者,GUID的全局和每个“ChildGuid”都可能是“ParentGuid”? – user7116

回答

5
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

2

我相信你可以使用的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() 
     }); 
0

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

3

这是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() 
} 

这是一种更容易维护的折腾。无论哪种方式,都不要在循环/查询中重新枚举myFlattenedHierarchy。

+0

我想你的第二个例子需要调整一下,'ParentGuid'和'ParentName'不是'row'的属性,还是我错过了一些东西? –

+0

@DogEars是的,行不在我使用它的范围内 - 编辑为使用g代替。 ParentGuid和ParentName在那里,因为这是一个flattenedHierarchy(每行中的父和子信息)。 –

+0

你能帮我用这个linq查询:http://stackoverflow.com/questions/38120664/how-to-group-by-on-2-child-entities-and-get-total-of-both-this柴尔德实体 –

0

这应该工作,与David 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() 
};