2011-09-29 46 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() 
};