和方法在 Linq 中可用Select
。Where
每个开发人员都应该了解这两种方法吗?例如:何时使用一种优于另一种,使用一种优于另一种的任何优势等。
8 回答
在哪里
查找匹配的项目并仅返回匹配的项目(过滤)。
IEnumerable<A>
- >IEnumerable<A>
进出
选择
为源中的所有项目返回一些东西(投影/转换)。那东西可能是物品本身,但更通常是某种投影。
IEnumerable<A>
- >IEnumerable<B>
进出
它们是不同的:
Select
都是关于转型。
Where
都是关于过滤的。
Select和Where是作用于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 上引入的其他运算符并推断它们的行为!
Where
~= 过滤器
Select
~= 地图
两者都返回IEnumerable<T>
Select 将可枚举映射到新结构。如果您对 IEnumerable 执行选择,您将获得一个具有相同数量元素的数组,但类型不同,具体取决于您指定的映射。Where 过滤 IEnumerable,以便它为您提供原始 IEnumerable 的子集。
如果你知道他们是如何实现 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 实现的扩展方法不同,因为它们使用表达式树来实现相同的。
如果选择它,您可以映射到新结构的 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> ]
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 不关心条件,它会映射所有内容,但关键是,它只会映射您想要准确映射的内容......
你不得不怀疑:
- 我到底需要从我拥有的所有这些值中映射什么?
- 我必须应用哪些条件才能仅过滤我需要的值(如果确实需要)?
希望这能照亮