Linq: Quelle est la différence entre Select et Where


122

Les méthodes Selectet Wheresont disponibles dans Linq. Que doit savoir chaque développeur sur ces deux méthodes? Par exemple: quand utiliser l'un par rapport à l'autre, les avantages de l'utilisation de l'un par rapport à l'autre, etc.


7
Je ne pense pas que cette question devrait être marquée comme CW, elle pourrait éventuellement avoir une réponse définitive.
Brandon

1
@Brandon il n'y a rien de mal à marquer quelque chose CW si c'est objectif.
Rex M

@Rex, je suis d'accord. Dire simplement que la différence entre Select et Where a une réponse définitive, et la deuxième partie de la question serait probablement basée sur des pratiques communément acceptées. Je le signalais simplement au cas où l'OP ne serait pas sûr de marquer des choses comme CW. S'il avait l'intention que ce soit CW, alors c'est très bien pour moi.
Brandon

6
Il y a beaucoup de mal à cela. CW est inutile, et le devient encore plus lorsque les gens marquent des questions complètement au hasard comme CW
jalf

Réponses:


126

trouve les éléments qui correspondent et ne renvoie que ceux qui le font ( filtrage ).

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

Sélectionner

renvoie quelque chose pour tous les éléments de la source ( projection / transformation ). Ce quelque chose pourrait être les éléments eux-mêmes, mais il s'agit plus généralement d'une projection.

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


15
Selectrenverra toujours le même nombre d'éléments dans la liste (quelle que soit la condition de filtre que vous pourriez avoir). Wherepeut renvoyer moins d'éléments en fonction de la condition de votre filtre.
goku_da_master

Et voici un exemple MSDN de selectet en voici un pourwhere
yazanpro

Au moins pour moi, ayant une certaine expérience avec d'autres langues, cela aide à penser que Where == filteretSelect == map
bgusach

52

Select et Where sont deux opérateurs complètement différents agissant sur les IEnumerable s.

Le premier est ce que nous appelons un opérateur de projection , tandis que le dernier est un opérateur de restriction .

Une manière intéressante d'avoir un aperçu du comportement de ces opérateurs est de regarder leur "type fonctionnel".

  • Sélectionnez: (IEnumerable <T1>, Func <T1, T2>) → IEnumerable <T2> ; il prend en entrée à la fois un IEnumerable contenant des éléments de type T1 et une fonction transformant des éléments de type T1 en éléments de type T2. La sortie est un IEnumerable contenant des éléments de type T2.

    À partir de là, on peut facilement deviner que cet opérateur produira sa sortie en appliquant la fonction d'entrée sur chaque élément de l'entrée IEnumerable et en enveloppant les résultats dans un nouveau IEnumerable.

    En utilisant une notation de type mathématique, il prend comme entrée (a, b, c, ...): IEnumerable <T1> et f: T1 → T2 et produit (f (a), f (b), f (c) , ...): IEnumerable <T2>

  • Où: (IEnumerable <T1>, Func <T1, bool>) → IEnumerable <T1> ; celui-ci prend un IEnumerable contenant des éléments de type T1 et un prédicat sur T1 (c'est-à-dire une fonction qui produit un résultat booléen pour une entrée de type T1). Vous voyez que la sortie est également un IEnumerable contenant des éléments de type T1.

    Cette fois, on devinerait qu'un élément de l'entrée IEnumerable sera présent sur la sortie IEnumerable en fonction du résultat de l'application du prédicat à l'élément. En ajoutant à cela la sémantique du nom de l'opérateur, vous pouvez être sûr qu'il produira la sortie IEnumerable en prenant de l'entrée un uniquement les éléments dont la valeur est vraie sur l'application du prédicat.

Les personnes ayant une formation en programmation fonctionnelle pensent généralement comme ça. Cela permet de déduire (ou du moins de deviner ...) ce que fait un opérateur uniquement en regardant son type!

En guise d'exercice, essayez de regarder d'autres opérateurs introduits par LINQ sur IEnumerables et en déduire leur comportement, avant de consulter la documentation!


47

Ils sont distincts:

Selectest une question de transformation .

Whereest une question de filtrage .


18

Select mappe un énumérable à une nouvelle structure. Si vous effectuez une sélection sur un IEnumerable, vous obtiendrez un tableau avec le même nombre d'éléments, mais un type différent selon le mappage que vous avez spécifié. Où filtre le IEnumerable afin qu'il vous donne un sous-ensemble du IEnumerable d'origine.


15

Where ~ = Filtre

Select ~ = Carte

Les deux retours IEnumerable<T>


C'est pour ça que je suis venu ici! Je vous remercie!
Ben Sandeen

7

Si vous savez comment ils ont implémenté Where et sélectionnez des méthodes d'extension, vous pouvez prédire ce qu'il fait ... J'ai essayé d'implémenter où et de sélectionner des méthodes d'extension ... Vous pouvez y jeter un œil ...

Où la mise en œuvre:

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

Sélectionnez l'implémentation ::

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

Mon implémentation fonctionne bien pour n'importe quelle collection ... Mais elle diffère des méthodes d'extension implémentées par Microsoft, car elles utilisent des arbres d'expression pour implémenter la même chose.


1

Dans le cas de Select it, vous pouvez mapper à un IEnumerable d'une nouvelle structure.

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

Where () fonctionne comme un filtre pour IEnumerable, il retournera le résultat sur la base de la clause where.

A.Where(x=>x.uid!=0) //input as [IEnumerable<A>] -------->  return output as [IEnumerable<A> ]
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.