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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12397880/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 23:07:16  来源:igfitidea点击:

Using LINQ, how to select conditionally some items but when no conditions select all?

c#linqselectsubset

提问by Stécy

I want to select elements from myCollection using myFilters for filtering:

我想使用 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

would return the "111" item.

将返回“111”项目。

However, if myFilters is empty I want to return all the items from myCollection.

但是,如果 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

would return all items ("111" and "999").

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

采纳答案by devgeezer

If these collections are going to be sizable, then I recommend using a join. It would look something like this:

如果这些集合会很大,那么我建议使用连接。它看起来像这样:

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;

Opportunities for using joins are easily overlooked. This join approach will outperform the contains approach when the lists are remotely large. If they're small and performance is acceptable, then use whichever seems the clearest.

使用连接的机会很容易被忽视。当列表非常大时,这种连接方法将优于包含方法。如果它们很小并且性能可以接受,那么使用看起来最清晰的那个。

回答by itsme86

The best you're going to be able to do is project the filters into SomeClass. Something like:

您将能够做的最好的事情是将过滤器投影到 SomeClass 中。就像是:

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

回答by horgh

Try this:

尝试这个:

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

Maybe it would be better to count filter collection only once:

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

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

EDIT

编辑

I'd even say that the answer by @itsme86 is correct, but, I guess, he has confused your collections. So his answer should look somehow like this:

我什至会说@itsme86 的答案是正确的,但是,我想,他混淆了您的收藏。所以他的回答应该是这样的:

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

回答by armen.shimoon

How about this?

这个怎么样?

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

Selecting from two collections performs a join based on your where clause. The join condition above says join on item.Name equal to filter OR select it if there are no filters available.

从两个集合中选择执行基于您的 where 子句的连接。上面的连接条件表示 item.Name 上的 join 等于过滤器或在没有可用过滤器时选择它。

回答by cuongle

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