Linq:SelectとWhereの違いは何ですか


122

SelectおよびWhere方法は、LINQの中で利用可能です。すべての開発者はこれら2つの方法について何を知っているべきですか?たとえば、どちらを使用するか、どちらを使用するかなどの利点があります。


7
この質問にCWのマークを付ける必要はないと思います。決定的な答えになる可能性があります。
ブランドン、

1
@Brandon客観的であれば、CWをマークしても問題はありません。
レックスM

@レックス、同意する。SelectとWhereの違いは明確な答えがあること、そして質問の2番目の部分は一般に受け入れられている慣行に基づいていると言っているだけです。OPがCWとしてマークすることについて確信が持てない場合に備えて、それを指摘していました。彼がCWであるつもりなら、私はそれで問題ありません。
ブランドン、

6
それには多くの誤りがあります。CWは役に立たず、人々が完全にランダムに質問をCWとしてマークすると、さらに
使いやすくなります

回答:


126

どこ

一致するアイテムを検索し、一致するアイテムのみを返します(フィルタリング)。

-> IEnumerable<A>イン、IEnumerable<A>アウト

選択する

ソース内のすべてのアイテムについて何かを返します(プロジェクション/変換)。それはアイテムそのものかもしれませんが、より一般的にはある種の予測です。

-> IEnumerable<A>イン、IEnumerable<B>アウト


15
Select常に同じ数の要素を返します(フィルター条件に関係なく)。 Whereフィルター条件に応じて、より少ない要素を返すことができます。
goku_da_master 2014年

そして、ここでのMSDNの例であるselect、ここに1つであるwhere
yazanpro

少なくとも私にとっては、他の言語とのいくつかの背景を持つ、その考えるのに役立ちますWhere == filterSelect == map
bgusach

52

SelectWhereは、IEnumerableに作用する2つの完全に異なる演算子です。

最初のものは射影演算子と呼ばれるもので、最後のものは制限演算子です。

そのような演算子の振る舞いを洞察する興味深い方法の1つは、その「関数型」を調べることです。

  • 選択:(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に存在すると推測します。これにオペレーター名のセマンティクスを追加すると、述語のアプリケーションでtrueと評価される要素のみを入力から取得することにより、出力IEnumerableが確実に生成されます。

関数型プログラミングのバックグラウンドを持つ人々は通常、このように考えます。それはあなたがそのタイプを見ることだけでオペレーターが何をするかを推測する(または少なくとも推測する)ことを可能にします!

演習として、ドキュメントを見る前に、IEnumerablesでLINQによって導入された他の演算子を見て、それらの動作を推測してみてください。



18

Selectは、列挙可能なオブジェクトを新しい構造にマップします。IEnumerableで選択を実行すると、要素数は同じですが、指定したマッピングに応じて型が異なる配列が取得されます。ここで、IEnumerableをフィルタリングして、元のIEnumerableのサブセットを提供します。



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が実装した拡張メソッドとは異なります。これらは式ツリーを使用して同じものを実装しているためです。


1

Select itの場合、新しい構造の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> ]
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.