C# 关于子列表性质的C Linq和滤波器

C# 关于子列表性质的C Linq和滤波器,c#,linq,list,C#,Linq,List,我尝试使用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> My

我尝试使用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;
最后

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 });
然后,使用此选项,我想筛选有关Property1的列表。 例如,我在true上的Property1上的筛选列表应该如下所示:

filtered_list = 1-1-1-true
我希望我足够清楚,否则我可以试着解释更多

最后,我的问题是:我想对列表应用Linq查询,以获得过滤后的列表。我试过了,在哪里。。。。我没有获得一个包含筛选子列表的列表

感谢您的帮助,并告诉我如何使用Linq筛选列表和子列表

编辑:我看到linq不可能或几乎在一步之内完成它。 因此,我考虑在dtb的帮助下,通过3个步骤实现另一个解决方案: -筛选所有MyClass2元素的所有MyClass3列表 -筛选MyClass3列表中至少有1个元素的MyClass2 -筛选MyClass1,其中MyClasses2列表中至少有1个元素

我设法做到了第三步,但第一步我没有做到。你能再帮我一次吗

我有一个方法RemoveClass3,可以帮助我在MyClass2声明中执行第一步

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();

递归地从列表中删除任何不需要的项可能比使用LINQ更优雅。

make helper extensions:

    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() 
               };
            }
          }
        }
      }
    }

谢谢你的快速回答!我明天一早试试,然后告诉你结果。谢谢所以我尝试了一下,但并没有完全奏效:列表被很好地过滤了,但MyClasses2和MyClasses3没有。在我的例子中,我得到的是前三行,而不是第一行。但是,当我更好地了解你的目的时,我相信我会理解为什么:Any不会过滤,但只会在一个元素正常时才查看。事实上,它有点复杂:我有3个类,我打印一个表,表中有一列,按类Id和名称打印。所以我不需要像1-2-3-4那样打印,只是为了更清晰地呈现。但事实并非如此:那我就放弃了。我不知道你想要什么。我对加载。。。这个过滤器在我的应用程序中使用过很多次,我认为递归性对于这个来说太重了…嗨!对不起,我迟了答复。事实上,我想避免foreach。。。这种方法会被多次使用,我认为linq比3 foreach更适合这种方法。现在,正如你在我的第一篇文章的编辑中所看到的,我想分三个步骤来完成这件事,我首先需要两个步骤的帮助。
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();
    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();
    }