Linq:Select和Where有什么区别

SBu*_*ris 113 .net linq select where

这些SelectWhere方法在Linq中可用.每个开发人员应该了解这两种方法?例如:何时使用一个优于另一个,使用一个优于另一个的任何优点,等等.

Dre*_*kes 112

哪里

查找匹配的项目,并仅返回执行的项目(过滤).

- > IEnumerable<A>进,IEnumerable<A>

选择

返回源中所有项目的内容(投影/转换).那些东西可能是物品本身,但通常更像某种投射.

- > IEnumerable<A>进,IEnumerable<B>

  • `Select`将始终返回列表中相同数量的元素(无论您可能具有过滤条件).`where`可以根据您的过滤条件返回更少的元素. (12认同)
  • 至少对我来说,有一些其他语言的背景,认为“Where == filter”和“Select == map”会有所帮助 (4认同)

Bru*_*eis 46

选择在哪里都作用在两个完全不同的运营商的IEnumerable秒.

第一个是我们称之为投影算子,而最后一个是限制算子.

了解此类运算符行为的一种有趣方式是查看其"功能类型".

  • 选择:(IEnumerable <T1>,Func <T1,T2>)→IEnumerable <T2> ; 它将包含T1类型元素的IEnumerable和将类型T1转换为T1类型元素的函数作为输入.输出是包含T2类型元素的IEnumerable.

    由此可以很容易地猜到,这个运算符将通过在输入IEnumerable的每个元素上应用输入函数并将结果包装在新的IEnumerable中来产生其输出.

    使用一些类似数学的表示法,它作为输入(a,b,c,...):IEnumerable <T1>f:T1→T2并产生(f(a),f(b),f(c) ,...):IEnumerable <T2>

  • 其中:(IEnumerable <T1>,Func <T1,bool>)→IEnumerable <T1> ; 这一个采用包含T1类型的元素的IEnumerable和T1上的谓词(即,为T1类型的输入生成布尔结果的函数).您会看到输出也是包含T1类型元素的IEnumerable.

    这一次可以猜测输入IEnumerable的元素将出现在输出IEnumerable上,具体取决于谓词应用于元素的结果.除此之外,运算符名称的语义还可以确保它将通过从输入中仅获取谓词应用程序中计算结果为true的元素来生成输出IEnumerable.

具有函数式编程背景的人通常会这样想.它允许你通过查看它的类型来推断(或至少猜测......)操作员所做的事情!

作为练习,在查看文档之前,尝试查看LINQ在IEnumerables上引入的其他运算符并推断它们的行为!


bru*_*nde 43

他们是不同的:

Select就是转型.

Where完全是关于过滤.


Ste*_*eve 18

选择将可枚举的映射映射到新结构.如果在IEnumerable上执行select,您将获得一个具有相同数量元素的数组,但是根据您指定的映射具有不同的类型.在哪里过滤IEnumerable,以便它为您提供原始IEnumerable的子集.


Dow*_*ski 9

Where 〜=筛选

Select 〜=地图

两种回报 IEnumerable<T>


小智 7

如果您知道他们如何实现Where和选择扩展方法,您可以预测它正在做什么......我试图在哪里实现并选择扩展方法......你可以看看它......

执行地点::

public static IEnumerable<Tsource> Where<Tsource> ( this IEnumerable<Tsource> a , Func<Tsource , bool> Method )
{

    foreach ( var data in a )
    {
        //If the lambda Expression(delegate) returns "true" Then return the Data. (use 'yield' for deferred return)
        if ( Method.Invoke ( data ) )
        {
            yield return data;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

选择实施::

public static IEnumerable<TResult> Select<TSource , TResult> ( this IEnumerable<TSource> a , Func<TSource , TResult> Method )
{
    foreach ( var item in a )
    {
        //Each iteration call the delegate and return the Data back.(use 'yield' for deferred return)
        yield return Method.Invoke ( item );
    }
}
Run Code Online (Sandbox Code Playgroud)

我的实现适用于任何集合......但它与Microsoft实现的扩展方法不同,因为它们使用表达式树来实现相同的.


And*_* Fg 6

List<string> randomList = new List<string> { "1", "2", "3" };        
var result = test.Where(value => value == "1");
Console.WriteLine(result.Count());
Run Code Online (Sandbox Code Playgroud)

会产生“1”作为结果,即过滤掉后包含对象“1”的结果。

List<string> randomList = new List<string> { "1", "2", "3" };        
var result = test.Select(value => value == "1");
Console.WriteLine(result.Count());
Run Code Online (Sandbox Code Playgroud)

即使条件匹配,也会产生“3”作为结果,因为它不会过滤。

结论:Where 检查条件。Select 并不关心***条件,它会映射所有内容,但重点是,它只会映射您想要精确映射的内容......(通过映射,这意味着,如果您愿意的话,可以阅读)。例如,在具有多个变量的类中,选择操作将允许您选择要读取的变量:

class Person
{
     public string Name { get;set; }
     public int Age { get;set; }       
}
Run Code Online (Sandbox Code Playgroud)

然后你可以拥有:

List<Person> persons = new();
List<string> namePersons = persons.Select(person => person.Name);
Run Code Online (Sandbox Code Playgroud)

它允许您仅映射列表中每个人的姓名。

Select 还可以实现“let”操作的功能(相当于链式 LINQ 扩展方法调用中的“let”关键字的代码

您还可以使用它来创建新对象,并在您阅读的列表中使用您想要使用的变量:

  List<Person> persons = new();
  var personsWithBlueEyes = persons.Select(person => new { Name=person.Name, Eyes="blue" });
Run Code Online (Sandbox Code Playgroud)

你一定想知道:

  1. 我到底需要从我拥有的所有这些值中映射出什么?
  2. 我必须应用哪些条件才能仅过滤我需要的值(如果确实需要)?

希望这能有所启发