140

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

4

8 回答 8

142

在哪里

查找匹配的项目并仅返回匹配的项目(过滤)。

IEnumerable<A>- >IEnumerable<A>进出

选择

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

IEnumerable<A>- >IEnumerable<B>进出

于 2009-07-31T14:16:08.797 回答
57

它们是不同的:

Select都是关于转型

Where都是关于过滤的。

于 2009-07-31T14:20:22.767 回答
53

SelectWhere是作用于IEnumerable的两个完全不同的运算符。

第一个是我们所说的投影算子,而最后一个是限制算子

了解此类运算符行为的一种有趣方法是查看它们的“功能类型”。

  • 选择 : (IEnumerable<T1>, Func<T1,T2>) → IEnumerable<T2> ; 它将包含 T1 类型元素的 IEnumerable 和将 T1 类型元素转换为 T2 类型元素的函数作为输入。输出是一个包含 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 上,这取决于对元素应用谓词的结果。再加上运算符名称的语义,您可以确保它将生成输出 IEnumerable,方法是从输入中仅获取那些在应用谓词时评估为真的元素。

函数式编程背景的人通常是这样想的。它允许您仅通过查看运算符的类型来推断(或至少猜测......)运算符的作用!

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

于 2009-08-04T23:13:15.327 回答
22

Where~= 过滤器

Select~= 地图

两者都返回IEnumerable<T>

于 2018-11-28T17:49:47.637 回答
18

Select 将可枚举映射到新结构。如果您对 IEnumerable 执行选择,您将获得一个具有相同数量元素的数组,但类型不同,具体取决于您指定的映射。Where 过滤 IEnumerable,以便它为您提供原始 IEnumerable 的子集。

于 2009-07-31T14:14:09.063 回答
7

如果你知道他们是如何实现 Where 和 select 扩展方法的,你可以预测它在做什么......我尝试实现 where 和 select 扩展方法......你可以看看它......

在哪里实施::

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

选择实施::

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

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

于 2014-04-22T06:10:49.037 回答
2

如果选择它,您可以映射到新结构的 IEnumerable。

  A.Select(x=>new X{UID=x.uid, UNAME=x.uname}) 
  //input as [IEnumerable<A>] -------->  return output as [IEnumerable<X> ]

Where() 用作 IEnumerable 的过滤器,它将根据 where 子句返回结果。

A.Where(x=>x.uid!=0) //input as [IEnumerable<A>] -------->  return output as [IEnumerable<A> ]
于 2019-09-27T06:47:09.017 回答
0
List<string> randomList = new List<string> { "1", "2", "3" };        
var result = test.Where(value => value == "1");
Console.WriteLine(result.Count());

结果会产生“1”,过滤掉包含对象“1”的那个。

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

结果将产生“3”,因为它不过滤,即使条件不匹配,它也会将其选择到“结果”列表中。

结论: Where 检查条件。Select 不关心条件,它会映射所有内容,但关键是,它只会映射您想要准确映射的内容......

你不得不怀疑:

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

希望这能照亮

于 2021-12-17T12:14:19.077 回答