2012-03-04 7 views
0

サブリストのプロパティのリストをlinqでフィルタリングしようとしましたが、正しく作成できません。 例えば、私はこれらのクラスC#Linqとサブサブリストのプロパティのフィルタ

public class MyClass1 
{ 
    public int Id { get; set; } 
    public List<MyClass2> MyClasses2 { get; private set; } 
} 

public class MyClass2 
{ 
    public int Id { get; set; } 
    public List<MyClass3> MyClasses3 { get; private set; } 
    /* EDIT */ 
    public virtual void RemoveClass3(MyClass3 elementToRemove) { ... } 
} 
public List<myClass2> myList2_1; 
public List<myClass2> myList2_2; 

public class MyClass3 
{ 
    public int Id { get; set; } 
    public Boolean Property1 { get; set; } 
} 
public List<myClass3> myList3_1; 
public List<myClass3> myList3_2; 
public List<myClass3> myList3_3; 

とデータ用があります。

myClass3 3A = new myClass3 { Id=1, Property1=true}; 
myClass3 3B = new myClass3 { Id=2, Property1=false}; 
myClass3 3C = new myClass3 { Id=3, Property1=false}; 
myClass3 3D = new myClass3 { Id=4, Property1=false}; 
myList3_1.AddRange(new []{ 3A, 3B }); 
myList3_2.AddRange(new []{ 3C }); 
myList3_3.AddRange(new []{ 3D }); 

myClass2 2A = new myClass2 { Id=1, MyClasses3=myList3_1}; 
myClass2 2B = new myClass2 { Id=2, MyClasses3=myList3_2}; 
myClass2 2C = new myClass2 { Id=3, MyClasses3=myList3_3}; 
myList2_1.AddRange(new []{ 2A, 2B }); 
myList2_2.AddRange(new []{ 2C }); 

し、最終的に

myClass1 1A = new MyClass1 { Id=1, MyClasses2=myList2_1 }; 
myClass1 1B = new MyClass1 { Id=2, MyClasses2=myList2_2 }; 
public List<MyClass1> list; 
list.AddRange(new []{ 1A, 1B }); 

我々はこのように印刷するには、リストを取得:

1-1-1-true 
1-1-2-false 
1-2-3-false 
2-3-4-false 

次に、これでProperty1のリストをフィルタリングしたいと思います。 例えば、真のプロパティ1の私のフィルタリングされたリストには、そのようにする必要があります:

filtered_list = 1-1-1-true 

私は他の私は多くを説明しようとすることができ、私は十分に明確だ願っています。

そして、私の問題:フィルタリングされたリストを取得するためにリストにLinqクエリを適用したいと思います。そして、私はAnyを試しました... ...私はフィルタリングされたサブリストを持つリストを取得できませんでした。

私を助けて、私は私のリストをフィルタリングするためのLINQを使用する方法を教えてくれとサブリストEDITため

ありがとう:私はそれは不可能だった見たか、ほぼ1つのステップでLINQでそれを作るために。 は、だから私はDTBの助けを借り、3つの段階で別の溶液で、考える: - であり、フィルタMyClass1 - MyClasses3リスト 中に少なくとも1の要素がある場合、フィルタMyClass2 - すべてすべてのMyClass2要素 のMyClass3リストをフィルタリングMyClasses2のリストで少なくとも1つの要素

私は3番目のステップを実行することができますが、最初は2番目のステップではありません。もう一度手伝ってもらえますか?

私は最初のステップのために支援するための方法RemoveClass3(私はMyClass2宣言に入れて)

答えて

0

これを試してみる:

var result = (from x in list 
       from y in x.MyClasses2 
       from z in y.MyClasses3 
       where z.Property1 
       group new { y, z } by x.Id into g1 
       select new MyClass1 
       { 
        Id = g1.Key, 
        MyClasses2 = (from p in g1 
           group p.z by p.y.Id into g2 
           select new MyClass2 
           { 
            Id = g2.Key, 
            MyClasses3 = (from r in g2 
                select new MyClass3 
                { 
                 Id = r.Id, 
                 Property1 = r.Property1 
                }).ToList() 
           }).ToList() 
       }).ToList(); 

再帰的に代わりlistから不要な項目を削除するために、よりエレガントてもよいですLINQを使用しています。

+0

感謝!私は明日早くそれを試し、結果を教えてくれるでしょう。ありがとう! – Remi

+0

私は試してみましたが、うまくいっていません:リストはよくフィルタリングされていますが、MyClasses2とMyClasses3はフィルタリングされていません。私の例では、最初の行ではなく3行の最初の行が得られます。しかし、私があなたの目的をよりよく見ているとき、私は理由を理解していると信じています:Any()はフィルターをかけません。それで、それはすべての要素(良いものと悪いもの)をもたらします。 – Remi

+0

実際、少し複雑です。3つのクラスがあり、クラスごとに1つの列のテーブルを印刷します(IDと名前が印刷されます)。だから、私は1-2-3-4のように印刷する必要はありません。もっと明確に提示するだけでした。しかしそれはありません:) – Remi

0

メイクヘルパー拡張:

public static class MyClassHelper 
    { 
     public static void Output(this MyClass1 item1) 
     { 
     Console.Write(item1.Id); 
     Console.Write("-"); 
     foreach (var item2 in item1.MyClasses2) 
     { 
      Console.Write(item2.Id); 
      Console.Write("-"); 
      foreach (var item3 in item2.MyClasses3) 
      { 
      Console.Write(item3.Id); 
      Console.Write("-"); 
      Console.Write(item3.Property1); 
      } 
     } 
     Console.WriteLine(); 
     } 
     public static IEnumerable<MyClass1> Flatten(this IEnumerable<MyClass1> list) 
     { 
     foreach (var item1 in list) 
     { 
      foreach (var item2 in item1.MyClasses2) 
      { 
      foreach (var item3 in item2.MyClasses3) 
      { 
       yield return new MyClass1 
       { 
       Id = item1.Id, 
       MyClasses2 = new[] 
       { 
        new MyClass2 { Id = item2.Id, MyClasses3 = new[]{item3}.ToList()} 
        }.ToList() 
       }; 
      } 
      } 
     } 
     } 
    } 

出力&フィルタこのレーザー・迅速な回答を

//output all 
    foreach (var item1 in list.Flatten()) 
    { 
     item1.Output(); 
    } 

    Console.WriteLine(); 

    //output filtered items 
    var filtered_list = list 
     .Flatten() 
     .Where(item1 => item1.MyClasses2 
      .Any(item2 => item2.MyClasses3 
      .Any(item3 => item3.Property1 == true) 
     ) 
     ) 
     .ToArray(); 

    foreach (var item1 in filtered_list) 
    { 
     item1.Output(); 
    } 
+0

こんにちは!返事遅れてすみません。実際には、私はforeachを避けたかった...このメソッドは何度も使用され、linqは3 foreachより良いこれだと思う。さて、第1稿の編集でわかるように、私は3つのステップでそれをやりたいのですが、まずは2つ目の助けが必要です。 – Remi

関連する問題