显示集合的子集合的特定元素

时间:2012-08-20 15:36:35

标签: c# linq

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

为了简化,我将主要集合THING和子集合SUBTHING。它们是不同的类型。可以有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的东西。

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

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

THING.ID
     SUBTHING.Name
     SUBTHING.Name

THING.ID
     SUBTHING.Name
     SUBTHING.Name

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

4 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

一种方法是使用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);
}

答案 2 :(得分:0)

在查询父实体(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))

答案 3 :(得分:0)

我不确定这些答案中的任何一个确实能给你你想要的东西(尽管它们很接近)。根据我的理解,您需要一个THING列表,其中至少有一个SUBTHING包含您感兴趣的值(在这种情况下,Prop1 == 1Prop2 != null) 。这里有几个选项,只取决于您是从THING还是SUBTHING工作。

选项1:THING方法。

您正在查看任何THING符合条件的SUBTHING。所以:

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方法。

您正在查看所有SUBTHING并找到符合条件的地方,并按照此处的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) };

我喜欢这种方法稍微好一些,但仍有改进的余地。我喜欢这个的原因是因为你首先找到了SUBTHING,然后才会提取与之关联的THING(而不是首先必须找到SUBTHING匹配的SUBTHING标准,然后选择它。)

选项3:混合方式。

这两者都有点。我们将从THING中选择任何一种方式,所以不妨只执行选择。然后,如果任何投影的子集合包含任何元素,那么我们会使用Names返回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

我认为最干净的选择。如果集合中有任何项目,则不带任何参数的集合上的{{1}}扩展方法将返回true。适合我们的情况。

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