2009-08-21 201 views
0

我使用LINQ從存儲過程調用中檢索到的對象集合中構建對象的樹形結構。Linq將元素從一個集合中移除到另一個集合中

我想知道,如果
一)有什麼辦法可以去除從一個集合的元素到一個新的集合
b)如居然有任何一點性能明智的在做這個

我的代碼看起來是像這樣:

class MyEntity 
{ 
    int ID { get; set; } 
    int? ParentID { get; set; } 
    string Name { get; set; } 
    List<MyEntity> children = new List<MyEntity>(); 
    List<MyEntity> Children { get { return children; } } 
} 

List<MyEntity> initialCollection = //get stuff from DB 

List<MyEntity> rootElements = (from e in initialCollection 
           where e.ParentID == null 
           select e).ToList(); 

List<MyEntity> childElements = (from e in initialCollection 
           where e.ParentID != null 
           select e).ToList(); 

foreach(MyElement e in rootElements) 
    e.Children.AddRange((from c in childElements 
         where c.ParentID == e.ID 
         select c).ToList()); 
//do some more recursion 

所以基本上;有沒有辦法做選擇語句,我真的從initialCollection刪除元素,因爲我選擇它們。這個想法是在遞歸構建我的樹時減少搜索元素的數量。這樣做實際上是否會有任何好處,或者是從一個集合中刪除元素並添加到另一個集合的開銷太大?

回答

3

一個更好的想法是創建一個查詢:

var childElements = initialCollection.Where(e => e.ParentID != null) 
            .ToLookup(e => e.ParentID); 

foreach (MyElement e in rootElements) 
{ 
    if (childElements.Contains(e.ID)) 
    { 
     e.Children.AddRange(childElements[e.ID]); 
    } 
} 

的查找是有點像Dictionary<TKey, IEnumerable<TValue>> - 所以基本上你的工作哪些孩子屬於哪一方,然後加入他們都在

認爲如果您有任何根元素沒有孩子,則需要調用Contains - 我希望索引器在指定鍵不存在的情況下拋出異常。文檔雖然不是很清楚 - 它可能會返回一個空序列。

+0

輝煌,非常乾淨的解決方案。乾杯。 – 2009-08-21 13:55:31

2

a)我不認爲你可以這樣做有幾個原因。首先,linq運算符用於評估表達式,因此不會影響源集合(或其他任何副作用)。其次,迭代器不允許在迭代期間修改源集合,因此在選擇過程中沒有任何機會去刪除元素。

B)這是不太可能,這將給出任何性能優勢 - 從列表中刪除的項目爲O(n),以便去除m項目將與O(MN),如果有很多的項目,以除去其中可能會相當緩慢。除非你真的需要空間,否則最好只是創建一個副本並使用它,在這種情況下,無論如何你都需要一個不同的數據結構。

相關問題