2009-08-21 17 views
0

私はLINQを使用して、ストアドプロシージャコールから取得したオブジェクトのコレクションからオブジェクトのツリー構造を構築しています。Linqはあるコレクションから別のコレクションに要素を削除します

私が実際に存在する場合、この

私のコードを実行中に賢明な任意のポイントのパフォーマンスが何かに見える)
a)の新しいコレクションに
Bを1つのコレクションから要素を削除するにはどのような方法があるかどうかを知りたいですこのように:

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 

だから基本的に; select文を実行する方法があります。実際には、要素を選択するにあたり、それらの要素を実際にはinitialCollectionから削除します。アイデアは、再帰的にツリーを構築しながら検索する要素の数を減らすことです。実際にこれを行うことで何か有益でしょうか、あるいはあるコレクションから要素を取り除き、別のコレクションに要素を追加するのにかかるオーバーヘッドですか?

答えて

3

Aはるかに良いアイデアは、ルックアップを作成するには、次のようになります。

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>>のようなものです - ので、基本的にはどの親、そして

でそれらのすべてを追加するために属する子どもワークアウト。

I 子供がいないルート要素がある場合は、Containsを呼び出す必要があります。指定されたキーが存在しない場合は、インデクサーが例外をスローすることが予想されます。ドキュメントはあまり明確ではありません。代わりに空のシーケンスを返すことがあります。

+0

ブリリアントは、本当に素晴らしいクリーンソリューションです。乾杯。 –

2

a)いくつかの理由でこれを行うことはできないと思います。まず、linq演算子は式を評価するために使用されるため、ソースコレクションに影響を与えません(またはその他の副作用がある)。第2に、イテレータは反復中にソースコレクションを変更することができないため、選択中に要素を削除する機会はありません。

b)リストからアイテムを削除するとO(n)が削除されるので、m個のアイテムを削除するとO(mn)になり、削除するアイテムがたくさんあるとかなり遅くなる可能性があります。あなたが実際に宇宙のためにプッシュされていない限り、コピーを作成して使用するほうが良いでしょう。その場合は、とにかに別のデータ構造が必要になります。