Linq: Qual è la differenza tra Select e Where


122

I metodi Selecte Wheresono disponibili in Linq. Cosa dovrebbe sapere ogni sviluppatore di questi due metodi? Ad esempio: quando usarli uno sull'altro, eventuali vantaggi nell'usare uno sull'altro, ecc.


7
Non penso che questa domanda debba essere contrassegnata come CW, potrebbe avere una risposta definitiva.
Brandon

1
@Brandon non c'è niente di sbagliato nel contrassegnare qualcosa in CW se è oggettivo.
Rex M

@ Rex, sono d'accordo. Sto solo dicendo che la differenza tra Select e Where ha una risposta definitiva, e la seconda parte della domanda sarebbe probabilmente basata su pratiche comunemente accettate. Lo stavo solo facendo notare nel caso in cui l'OP non fosse sicuro di contrassegnare le cose come CW. Se intendeva che fosse CW, allora per me va bene.
Brandon

6
C'è molto di sbagliato in questo. Il CW è inutile e lo diventa di più quando le persone contrassegnano le domande in modo completamente casuale come CW
jalf

Risposte:


126

Dove

trova gli elementi che corrispondono e restituisce solo quelli che lo fanno ( filtraggio ).

-> IEnumerable<A>dentro, IEnumerable<A>fuori

Selezionare

restituisce qualcosa per tutti gli elementi nell'origine ( proiezione / trasformazione ). Quel qualcosa potrebbe essere gli oggetti stessi, ma più di solito sono una proiezione di qualche tipo.

-> IEnumerable<A>dentro, IEnumerable<B>fuori


15
Selectrestituirà sempre lo stesso numero di elementi nell'elenco (indipendentemente dalla condizione di filtro che potresti avere). Wherepuò restituire meno elementi a seconda della condizione del filtro.
goku_da_master

Ed ecco un esempio MSDN di selected eccone uno perwhere
yazanpro

Almeno per me, avendo un po 'di esperienza con altre lingue, aiuta pensare che Where == filtereSelect == map
bgusach

52

Select e Where sono due operatori completamente diversi che agiscono su IEnumerable s.

Il primo è quello che chiamiamo un operatore di proiezione , mentre l'ultimo è un operatore di restrizione .

Un modo interessante per avere un'idea del comportamento di tali operatori è dare uno sguardo al loro "tipo funzionale".

  • Selezionare: (IEnumerable <T1>, Func <T1, T2>) → IEnumerable <T2> ; prende come input sia un IEnumerable contenente elementi di tipo T1 sia una funzione che trasforma elementi di tipo T1 in elementi di tipo T2. L'output è un IEnumerable contenente elementi di tipo T2.

    Da ciò, si può facilmente intuire che questo operatore produrrà il suo output applicando la funzione di input su ogni elemento dell'input IEnumerable e avvolgendo i risultati in un nuovo IEnumerable.

    Utilizzando alcuni matematica simile notazione, prende come input (a, b, c, ...): IEnumerable <T1> e f: T1 → T2 e produce (f (a), f (b), f (c) , ...): IEnumerable <T2>

  • Dove: (IEnumerable <T1>, Func <T1, bool>) → IEnumerable <T1> ; questo accetta un IEnumerable contenente elementi di tipo T1 e un predicato su T1 (cioè una funzione che produce un risultato booleano per un input di tipo T1). Si vede che l'output è anche un IEnumerable contenente elementi di tipo T1.

    Questa volta si potrebbe ipotizzare che un elemento dell'input IEnumerable sarà presente sull'output IEnumerable a seconda del risultato dell'applicazione del predicato all'elemento. Aggiungendo a ciò la semantica del nome dell'operatore, si può essere certi che produrrà l'output IEnumerable prendendo dall'input solo quegli elementi che valgono true sull'applicazione del predicato.

Le persone con un background di programmazione funzionale di solito la pensano così. Ti permette di dedurre (o almeno indovinare ...) cosa fa un operatore solo guardando il suo tipo!

Come esercizio, prova a guardare altri operatori introdotti da LINQ su IEnumerables e deduci il loro comportamento, prima di guardare la documentazione!


47

Sono distinti:

Selectè tutta una questione di trasformazione .

Whereriguarda il filtraggio .


18

Seleziona mappa un enumerabile su una nuova struttura. Se esegui una selezione su un oggetto IEnumerable, otterrai un array con lo stesso numero di elementi, ma un tipo diverso a seconda della mappatura specificata. Where filtra l'IEnumerable in modo da fornire un sottoinsieme dell'originale IEnumerable.



7

Se sai come hanno implementato Dove e seleziona i metodi di estensione puoi prevedere cosa sta facendo ... Ho provato a implementare dove e selezionare i metodi di estensione ... Puoi dare un'occhiata ...

Dove implementazione:

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

Seleziona implementazione:

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

La mia implementazione funziona bene per qualsiasi raccolta ... Ma differisce dai metodi di estensione implementati da Microsoft, perché usano alberi delle espressioni per implementare lo stesso.


1

In caso di Seleziona è possibile mappare a un IEnumerable di una nuova struttura.

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

Where () funziona come filtro per IEnumerable, restituirà il risultato sulla base della clausola where.

A.Where(x=>x.uid!=0) //input as [IEnumerable<A>] -------->  return output as [IEnumerable<A> ]
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.