2012-03-04 5 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. Например, мой отфильтрованный список на property1 по истине должно быть так:

filtered_list = 1-1-1-true 

Я надеюсь, что я достаточно ясно, я еще могу попытаться объяснить больше.

И чтобы закончить, моя проблема: я хочу применить запрос Linq к списку, чтобы получить filter_list. И я попробовал Any, Where .... Мне не удалось получить список с фильтрованными подсписками.

Спасибо за помощь мне и сказать, как я могу использовать Linq фильтровать свой список и подсписки

EDIT: Я видел, что это было невозможно или почти сделать это с помощью LINQ в 1 шаг. Итак, я думаю, с помощью dtb, другое решение в 3 этапа: - отфильтровать все списки MyClass3 всех элементов MyClass2 - фильтр MyClass2, где есть список из 1 MyClasses3 в списке MyClasses3 - фильтр MyClass1, где есть наименее 1 элемент в списке MyClasses2

Мне удается сделать 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 класса, и я печатаю таблицу с одним столбцом по классу (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

Смежные вопросы