使用LINQ,如何有条件地选择一些项目,但没有条件选择全部?

时间:2012-09-13 00:33:22

标签: c# linq select subset

我想使用myFilters从myCollection中选择元素进行过滤:

var myFilters = new List<string> {"111", "222"};
var myCollection = new List<SomeClass> {
                      new SomeClass ("111"), 
                      new SomeClass ("999")
                   };

from filter in myFilters
from item in myCollection
where item.Name == filter
select item

将返回“111”项。

但是,如果myFilters为空,我想从myCollection中返回所有项目。

var myFilters = new List<string> ();
var myCollection = new List<SomeClass> {
                          new SomeClass ("111"), 
                          new SomeClass ("999")
                    };

// Here's where I'm lost...
from filter in myFilters
from item in myCollection
where item.Name == filter
select item

将返回所有项目(“111”和“999”)。

5 个答案:

答案 0 :(得分:7)

如果这些集合规模可观,那么我建议使用连接。它看起来像这样:

var result = 
    myFilters.Any() ?
        from item in myCollection
        join filter in myFilters
        on item.Name equals filter into gj
        where gj.Any()
        select item
    : myCollection;

使用连接的机会很容易被忽视。当列表远程大时,此连接方法将优于包含方法。如果它们很小并且性能可以接受,那么请使用最清晰的。

答案 1 :(得分:4)

var result = myCollection
                   .Where(i => (!myFilters.Any() || myFilters.Contains(i.Name)));

答案 2 :(得分:1)

你能做的最好的事情是将过滤器投射到SomeClass中。类似的东西:

var results = myCollection.Any() ?
    myCollection.Where(item => myFilters.Contains(item.Name)) :
    myFilters.Select(f => new SomeClass (f));

答案 3 :(得分:0)

试试这个:

var result = myCollection.Where(s => !myFilters.Any() ||
                                     myFilters.Contains(s.Name));
//EDIT: commented these lines..based on comment by @Servy
//var result = myCollection.Where(s => myFilters.Count == 0 ||
//                                     myFilters.Contains(s.Name));

也许最好只计算一次过滤器集合:

bool isFilterEmpty = !myFilters.Any(); 
//bool isFilterEmpty = myFilters.Count == 0;    //...or like this
var result = myCollection.Where(s => isFilterEmpty || 
                                     myFilters.Contains(s.Name));

修改

我甚至会说@ itsme86的答案是正确的,但是,我想,他已经把你的收藏混淆了。所以他的答案看起来应该是这样的:

var results = myFilters.Any()
                 ? myCollection.Where(item => myFilters.Contains(item.Name))
                 : myCollection;

答案 4 :(得分:0)

这个怎么样?

var myFilters = new List<string> ();
var myCollection = new List<SomeClass> {new SomeClass ("111"), new SomeClass ("999")};

// Here's where I'm lost...
from filter in myFilters
from item in myCollection
where item.Name == filter || !myFilters.Any()
select item

从两个集合中进行选择会根据您的where子句执行连接。上面的连接条件表示join.Name上的join等于filter OR如果没有可用的过滤器,则选择它。