Linq: Select和Where之间的区别是什么

时间:2022-09-05 11:50:53

The Select and Where methods are available in Linq. What should every developer know about these two methods? For example: when to use one over the other, any advantages of using one over the other, etc.

在Linq中可以使用Select和Where方法。对于这两种方法,每个开发人员应该了解什么?例如:when to use one over the other, any advantages of use one over the other等等。

5 个解决方案

#1


95  

Where

在哪里

finds items that match and only returns those that do (filtering).

查找匹配的项,并只返回那些匹配的项(过滤)。

-> IEnumerable<A> in, IEnumerable<A> out

-> IEnumerable; IEnumerable = A

Select

选择

returns something for all items in the source (projection / transformation). That something might be the items themselves, but are more usually a projection of some sort.

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

-> IEnumerable<A> in, IEnumerable<B> out

-> IEnumerable, IEnumerable out。

#2


38  

Select and Where are two completely different operators acting on IEnumerables.

Select和Where是作用于IEnumerables的两个完全不同的操作符。

The first one is what we call a Projection Operator, while the last one is a Restriction Operator.

第一个是投影算子,最后一个是限制算子。

One interesting way to have insight on the behavior of such operators is to take a look at their "functional type".

了解这些操作符的行为的一个有趣的方法是查看它们的“功能类型”。

  • Select : (IEnumerable<T1>, Func<T1,T2>) → IEnumerable<T2>; it takes as input both an IEnumerable containing elements of type T1 and a function transforming elements of type T1 into elements of type T2. The output is an IEnumerable containing elements of type T2.

    选择:(IEnumerable < T1 >,Func < T1,T2 >)→IEnumerable < T2 >;它接受包含T1类型元素的IEnumerable和将T1类型的元素转换为T2类型的元素的函数。输出是一个IEnumerable,包含T2类型的元素。

    From this, one can easily guess that this operator will produce its output by applying the input function on each element of the input IEnumerable, and wrapping the results inside a new IEnumerable.

    由此,我们可以很容易地猜测这个操作符将通过在输入IEnumerable上应用输入函数来产生输出,并将结果封装在一个新的IEnumerable内。

    Using some math-like notation, it takes as input (a, b, c, ...) : IEnumerable<T1> and f : T1 → T2 and produces (f(a), f(b), f(c), ...) : IEnumerable<T2>

    使用一些算术类符号,它需要作为输入(a,b,c,…):IEnumerable < T1 >和f:T1→T2和生产(f(a),f(b),f(c),…):IEnumerable < T2 >

  • Where : (IEnumerable<T1>, Func<T1, bool>) → IEnumerable<T1> ; this one takes an IEnumerable containing elements of type T1 and a predicate on T1 (that is, a function that produces a boolean result for an input of type T1). You see that the output is also an IEnumerable containing elements of type T1.

    地点:(IEnumerable < T1 >,Func < T1,bool >)→IEnumerable < T1 >;这个函数接受包含类型为T1的元素的IEnumerable和T1上的谓词(即为类型为T1的输入生成布尔结果的函数)。您可以看到输出也是一个IEnumerable,包含类型为T1的元素。

    This time one would guess that an element of the input IEnumerable will be present on the output IEnumerable depending on the result of the application of the predicate to the element. Adding to this the semantics of the operator name, you can be sure that it will produce the output IEnumerable by taking from the input one only those elements that evaluates to true on the application of the predicate.

    这一次,我们可以猜测输入IEnumerable的一个元素会出现在输出IEnumerable上,这取决于对元素应用谓词的结果。除了操作符名称的语义之外,您还可以通过只从输入1中获取在谓词的应用程序上计算为true的元素来确保输出IEnumerable。

People with functional programming background usually think like this. It allows you to deduce (or at least guess...) what an operator does only by looking at it's type!

具有函数式编程背景的人通常是这样想的。它允许你推断(或者至少猜一下…)一个操作符只通过查看它的类型来做什么!

As an exercise, try to look at other operators introduced by LINQ on IEnumerables and deduce their behavior, before looking at the documentation!

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

#3


34  

They are distinct:

他们是不同的:

Select is all about transformation.

Select都是关于转换的。

Where is all about filtering.

所有关于过滤的内容。

#4


15  

Select maps an enumerable to a new structure. If you perform a select on an IEnumerable, you will get an array with the same number of elements, but a different type depending on the mapping you specified. Where filters the IEnumerable so that it gives you a subset of the original IEnumerable.

选择映射到一个新结构的枚举。如果在IEnumerable上执行select,就会得到一个元素数目相同但类型不同的数组,这取决于您指定的映射。过滤IEnumerable,这样它就会给你原来IEnumerable的子集。

#5


6  

If you know how they have implemented Where and select extension methods you can predict what it is doing... I tried to implement where and select extension methods... You can have a look at it...

如果您知道它们是如何实现的,并选择扩展方法,您就可以预测它正在做什么……我试图实现where并选择扩展方法……你可以看一下……

Where Implementation ::

实现::

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

Select implementation ::

选择实现::

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

My implementation works fine for any collection... But it differs from Microsoft implemented Extension methods, Because they use expression trees to implement the same.

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

#1


95  

Where

在哪里

finds items that match and only returns those that do (filtering).

查找匹配的项,并只返回那些匹配的项(过滤)。

-> IEnumerable<A> in, IEnumerable<A> out

-> IEnumerable; IEnumerable = A

Select

选择

returns something for all items in the source (projection / transformation). That something might be the items themselves, but are more usually a projection of some sort.

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

-> IEnumerable<A> in, IEnumerable<B> out

-> IEnumerable, IEnumerable out。

#2


38  

Select and Where are two completely different operators acting on IEnumerables.

Select和Where是作用于IEnumerables的两个完全不同的操作符。

The first one is what we call a Projection Operator, while the last one is a Restriction Operator.

第一个是投影算子,最后一个是限制算子。

One interesting way to have insight on the behavior of such operators is to take a look at their "functional type".

了解这些操作符的行为的一个有趣的方法是查看它们的“功能类型”。

  • Select : (IEnumerable<T1>, Func<T1,T2>) → IEnumerable<T2>; it takes as input both an IEnumerable containing elements of type T1 and a function transforming elements of type T1 into elements of type T2. The output is an IEnumerable containing elements of type T2.

    选择:(IEnumerable < T1 >,Func < T1,T2 >)→IEnumerable < T2 >;它接受包含T1类型元素的IEnumerable和将T1类型的元素转换为T2类型的元素的函数。输出是一个IEnumerable,包含T2类型的元素。

    From this, one can easily guess that this operator will produce its output by applying the input function on each element of the input IEnumerable, and wrapping the results inside a new IEnumerable.

    由此,我们可以很容易地猜测这个操作符将通过在输入IEnumerable上应用输入函数来产生输出,并将结果封装在一个新的IEnumerable内。

    Using some math-like notation, it takes as input (a, b, c, ...) : IEnumerable<T1> and f : T1 → T2 and produces (f(a), f(b), f(c), ...) : IEnumerable<T2>

    使用一些算术类符号,它需要作为输入(a,b,c,…):IEnumerable < T1 >和f:T1→T2和生产(f(a),f(b),f(c),…):IEnumerable < T2 >

  • Where : (IEnumerable<T1>, Func<T1, bool>) → IEnumerable<T1> ; this one takes an IEnumerable containing elements of type T1 and a predicate on T1 (that is, a function that produces a boolean result for an input of type T1). You see that the output is also an IEnumerable containing elements of type T1.

    地点:(IEnumerable < T1 >,Func < T1,bool >)→IEnumerable < T1 >;这个函数接受包含类型为T1的元素的IEnumerable和T1上的谓词(即为类型为T1的输入生成布尔结果的函数)。您可以看到输出也是一个IEnumerable,包含类型为T1的元素。

    This time one would guess that an element of the input IEnumerable will be present on the output IEnumerable depending on the result of the application of the predicate to the element. Adding to this the semantics of the operator name, you can be sure that it will produce the output IEnumerable by taking from the input one only those elements that evaluates to true on the application of the predicate.

    这一次,我们可以猜测输入IEnumerable的一个元素会出现在输出IEnumerable上,这取决于对元素应用谓词的结果。除了操作符名称的语义之外,您还可以通过只从输入1中获取在谓词的应用程序上计算为true的元素来确保输出IEnumerable。

People with functional programming background usually think like this. It allows you to deduce (or at least guess...) what an operator does only by looking at it's type!

具有函数式编程背景的人通常是这样想的。它允许你推断(或者至少猜一下…)一个操作符只通过查看它的类型来做什么!

As an exercise, try to look at other operators introduced by LINQ on IEnumerables and deduce their behavior, before looking at the documentation!

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

#3


34  

They are distinct:

他们是不同的:

Select is all about transformation.

Select都是关于转换的。

Where is all about filtering.

所有关于过滤的内容。

#4


15  

Select maps an enumerable to a new structure. If you perform a select on an IEnumerable, you will get an array with the same number of elements, but a different type depending on the mapping you specified. Where filters the IEnumerable so that it gives you a subset of the original IEnumerable.

选择映射到一个新结构的枚举。如果在IEnumerable上执行select,就会得到一个元素数目相同但类型不同的数组,这取决于您指定的映射。过滤IEnumerable,这样它就会给你原来IEnumerable的子集。

#5


6  

If you know how they have implemented Where and select extension methods you can predict what it is doing... I tried to implement where and select extension methods... You can have a look at it...

如果您知道它们是如何实现的,并选择扩展方法,您就可以预测它正在做什么……我试图实现where并选择扩展方法……你可以看一下……

Where Implementation ::

实现::

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

Select implementation ::

选择实现::

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

My implementation works fine for any collection... But it differs from Microsoft implemented Extension methods, Because they use expression trees to implement the same.

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