【问题标题】:Displaying specific elements of a collection's subcollection显示集合的子集合的特定元素
【发布时间】:2012-08-20 15:36:35
【问题描述】:

我有一个 List 集合,其中包含一个 List 子集合作为其中的属性,我想根据某些属性的值过滤掉该子集合中的项目。

为简化起见,我将主集合称为 THING 和子集合 SUBTHING。它们是不同的类型。 THINGS 可以有 1 到多个 SUBTHINGS。 SUBTHING 有 2 个我要过滤的属性,PROP1 应该等于 1(它可以等于 1,2,3)并且 PROP2 不应该是 NULL(它可以包含一个字符串)。

因此,当我使用如下查询时,它似乎给了我想要的东西(尽管我不确定 All() 是否符合我的预期):

search = from c in search
where c.SUBTHING.All(s=>s.PROP1==1)
select c;

然后当我添加其他属性时我会怀疑:

search = from c in search
where c.SUBTHING.All(s=>s.PROP1==1 && s.PROP2 != NULL)
select c;

我得到了 PROP2 为 Null 的 THINGS。

当我切换到 Any() 时,我失去了对 SUBTHING 的所有过滤,它显示了 PROP1 = 1、2、3 和 PROP2 为 NULL 而不是 NULL 的 SUBTHINGS。

我想要得到的是一个集合,它列出了所有 THING ID,然后列出了所有 SUBTHINGS 的名称,有点像这样:

THING.ID
     SUBTHING.Name
     SUBTHING.Name

THING.ID
     SUBTHING.Name
     SUBTHING.Name

由于 THING 和 SUBTHING 是两种不同的类型,是否可以在使用 LINQ 过滤 THINGS 的同时过滤 SUBTHINGS?

【问题讨论】:

  • “我想要得到的是一个列出所有 SUBTHING ID 的集合......” 是一个错字,应该是 “我想要得到的是一个列出所有 THING ID 的集合......” ?!
  • @ewomack,您是否尝试在搜索中修改 c 以使除 SUBTHING 被过滤之外的所有内容都具有完全相同的值?
  • 如果我对您的理解正确,您希望整个层次结构中的所有 SUBTHINGS 具有 PROP1=1 和 PROP2!=Null 以及它们对应的 THING.ID....对吗?
  • @Tim,是的,你是对的,这是一个错字。固定的。谢谢!
  • @M Afifi 和 DarkSquirrel,是的,你们俩听起来都对 - 我正在尝试从 THINGS-->SUBTHINGS 的层次结构中过滤子集合 SUBTHINGS。

标签: c# linq


【解决方案1】:

试试这样的:

search = 
    from c in search 
    where c.SUBTHING.All(s=>s.PROP1==1 && s.PROP2 != NULL) 
    select new {
         ThingId = c.ThingID,
         Something = c.SomeThing.Select(x=>x.Name)
     }; 

要对子项应用过滤器,请尝试:

from product in products
where product.productid == 1
from image in product.productimages
where image.ismainimage
select image.imagename

发件人:101 linq queries

【讨论】:

    【解决方案2】:

    一种方法是使用Enumerable.Where 和匿名类型:

    var result = from thing in search
             from subthing in thing.subthings
             where subthing.prop1 == 1 && subthing.prop2 != null
             select new {ID = thing.ID, Name = subthing.Name};
    
    foreach(var x in result)
    {
        Console.WriteLine("ID={0} Name{1}", x.ID, x.Name);
    }
    

    【讨论】:

      【解决方案3】:

      您在查询父实体 (THING) 时需要一个投影,但在结果集中您只想拥有其 SUBTHINGS 的一个子集。

      你可以做到,例如通过以下方式:

      class Thing
      {
          Thing(Thing original, IEnumerable<Subthing> subthings)
          {
              // Initialize based on original and set the collection
              //
              ...
          }
      }
      

      然后像这样运行查询:

      var filtered = from c in search
                     select new Thing(c, c.Subthings.Where(x => x.PROP1 == 1 && x.PROP2 != null))
      

      【讨论】:

        【解决方案4】:

        我不确定这些答案是否真的能满足您的需求(尽管它们很接近)。据我了解,您需要一个 THINGs 列表,其中至少 1 个 SUBTHING 具有您感兴趣的值(在本例中为 Prop1 == 1Prop2 != null)。这里有几个选项,仅取决于您是从THING 还是SUBTHING 角度工作。

        选项 1:THING 方法。

        您正在查看任何具有SUBTHINGTHING 符合您的条件。所以:

        var result = from thing in search
                     where thing.Subthings.Any(tr => tr.Prop1 == 1 && tr.Prop2 != null)
                     select new { ID = thing.ID, Names = thing.Subthings.Where(tr => tr.Prop1 == 1 && tr.Prop2 != null) };
        

        选项 2:SUBTHING 方法。

        您正在查看 ALL SUBTHINGs 并找到满足条件的那些,然后按 ID 分组。

        var result = from thing in search
                     from sub in thing.Subthings
                     where sub.Prop1 == 1 && sub.Prop2 != null
                     group sub by thing.id into sg
                     select new { ID = sg.Key, Names = sg.Select(tr => tr.Name) };
        

        我更喜欢这种方法,但仍有改进的余地。我喜欢这个的原因是因为你首先找到SUBTHINGs,然后它才会拉出与之关联的THING(而不是首先必须查找是否有任何SUBTHING符合条件,然后选择它)。

        选项 3:混合方法。

        两者兼而有之。无论哪种方式,我们都将从SUBTHINGs 中进行选择,因此不妨执行选择。然后,如果任何投影的子集合有任何元素,那么我们返回 THINGNames

        var result = from thing in search
                     let names = thing.Subthings
                                      .Where(sub => sub.Prop1 == 1 && sub.Prop2 != null)
                                      .Select(sub => sub.Name)
                     where names.Any()
                     select new { ID = thing.ID, Names = names };
        

        在我看来,最干净的选择。如果集合中有任何项,则不带任何参数的集合上的 Any 扩展方法将返回 true。非常适合我们的情况。

        希望对您有所帮助,让我们知道您的想法。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-12-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-09-16
          • 2014-05-03
          相关资源
          最近更新 更多