SelectI Wheremetody są dostępne w Linq. Co każdy programista powinien wiedzieć o tych dwóch metodach? Na przykład: kiedy używać jednego nad drugim, jakie są zalety używania jednego nad drugim itp.
Myślę, że to pytanie nie powinno być oznaczone jako CW, prawdopodobnie mogłoby mieć ostateczną odpowiedź.
Brandon,
1
@Brandon nie ma nic złego w oznaczaniu czegoś CW, jeśli jest to obiektywne.
Rex M
@Rex, zgadzam się. Samo stwierdzenie, że różnica między Select i Where ma ostateczną odpowiedź, a druga część pytania byłaby prawdopodobnie oparta na powszechnie przyjętych praktykach. Wskazałem to tylko na wypadek, gdyby OP nie był pewien co do oznaczania rzeczy jako CW. Jeśli zamierzał, aby było CW, to jest w porządku.
Brandon
6
Jest w tym wiele nie tak. CW jest bezużyteczne, a staje się coraz większe, gdy ludzie zaznaczają pytania całkowicie losowo jako CW
jalf
Odpowiedzi:
127
Gdzie
znajduje pasujące elementy i zwraca tylko te, które pasują ( filtrowanie ).
-> IEnumerable<A>na IEnumerable<A>zewnątrz
Wybierz
zwraca coś dla wszystkich elementów w źródle ( projekcja / transformacja ). Tym czymś mogą być same przedmioty, ale zazwyczaj są to jakieś projekcje.
Selectzawsze zwróci tę samą liczbę elementów na liście (niezależnie od warunku filtru, który możesz mieć). Wheremoże zwrócić mniej elementów w zależności od stanu filtra.
goku_da_master
A oto przykład MSDN selecti tutaj jest jeden dlawhere
yazanpro
Przynajmniej dla mnie, mając pewne doświadczenie z innymi językami, pomaga to pomyśleć Where == filteriSelect == map
bgusach
52
Select i Where to dwa zupełnie różne operatory działające na IEnumerable s.
Pierwszy to tak zwany operator projekcji , a ostatni to operator ograniczeń .
Ciekawym sposobem uzyskania wglądu w zachowanie takich operatorów jest przyjrzenie się ich „typowi funkcjonalnemu”.
Wybierz: (IEnumerable <T1>, Func <T1, T2>) → IEnumerable <T2> ; przyjmuje jako dane wejściowe zarówno IEnumerable zawierające elementy typu T1, jak i funkcję przekształcającą elementy typu T1 na elementy typu T2. Dane wyjściowe to IEnumerable zawierające elementy typu T2.
Na tej podstawie można łatwo zgadnąć, że ten operator wygeneruje dane wyjściowe, stosując funkcję wejściową do każdego elementu wejściowego IEnumerable i zawijając wyniki do nowego IEnumerable.
Za pomocą matematycznej jak notacji trwa na wejściu (a, b, c, ...) IEnumerable <T1> i f T1 → T2 i wytwarza (F (a), F (b), f (c) , ...): IEnumerable <T2>
Gdzie: (IEnumerable <T1>, Func <T1, bool>) → IEnumerable <T1> ; ten pobiera element IEnumerable zawierający elementy typu T1 i predykat na T1 (to znaczy funkcję, która generuje wynik boolowski dla danych wejściowych typu T1). Widzisz, że dane wyjściowe są również IEnumerable zawierające elementy typu T1.
Tym razem można by się domyślić, że element wejściowy IEnumerable będzie obecny na wyjściu IEnumerable w zależności od wyniku zastosowania predykatu do elementu. Dodając do tego semantykę nazwy operatora, możesz być pewien, że wygeneruje on wynik IEnumerable, pobierając z danych wejściowych tylko te elementy, które są szacowane na true w zastosowaniu predykatu.
Ludzie z doświadczeniem w programowaniu funkcjonalnym zwykle myślą w ten sposób. Pozwala wywnioskować (lub przynajmniej zgadywać ...), co robi operator, tylko patrząc na jego typ!
W ramach ćwiczenia spróbuj spojrzeć na inne operatory wprowadzone przez LINQ na IEnumerables i wydedukować ich zachowanie, zanim przejrzysz dokumentację!
Select mapuje wyliczalną do nowej struktury. Jeśli dokonasz wyboru na IEnumerable, otrzymasz tablicę z taką samą liczbą elementów, ale innym typem w zależności od określonego mapowania. Where filtruje IEnumerable, aby uzyskać podzbiór oryginalnego IEnumerable.
Jeśli wiesz, jak zaimplementowali Gdzie i wybierz metody rozszerzeń, możesz przewidzieć, co robi ... Próbowałem zaimplementować gdzie i wybrać metody rozszerzeń ... Możesz na to spojrzeć ...
Gdzie Wdrożenie ::
publicstaticIEnumerable<Tsource>Where<Tsource>(thisIEnumerable<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 )){yieldreturn data;}}}
Wybierz realizację:
publicstaticIEnumerable<TResult>Select<TSource,TResult>(thisIEnumerable<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)yieldreturnMethod.Invoke( item );}}
Moja implementacja działa dobrze dla każdej kolekcji ... Ale różni się od metod rozszerzeń zaimplementowanych przez Microsoft, ponieważ używają drzew wyrażeń do implementacji tego samego.
Odpowiedzi:
Gdzie
znajduje pasujące elementy i zwraca tylko te, które pasują ( filtrowanie ).
->
IEnumerable<A>
naIEnumerable<A>
zewnątrzWybierz
zwraca coś dla wszystkich elementów w źródle ( projekcja / transformacja ). Tym czymś mogą być same przedmioty, ale zazwyczaj są to jakieś projekcje.
->
IEnumerable<A>
naIEnumerable<B>
zewnątrzźródło
Select
zawsze zwróci tę samą liczbę elementów na liście (niezależnie od warunku filtru, który możesz mieć).Where
może zwrócić mniej elementów w zależności od stanu filtra.select
i tutaj jest jeden dlawhere
Where == filter
iSelect == map
Select i Where to dwa zupełnie różne operatory działające na IEnumerable s.
Pierwszy to tak zwany operator projekcji , a ostatni to operator ograniczeń .
Ciekawym sposobem uzyskania wglądu w zachowanie takich operatorów jest przyjrzenie się ich „typowi funkcjonalnemu”.
Wybierz: (IEnumerable <T1>, Func <T1, T2>) → IEnumerable <T2> ; przyjmuje jako dane wejściowe zarówno IEnumerable zawierające elementy typu T1, jak i funkcję przekształcającą elementy typu T1 na elementy typu T2. Dane wyjściowe to IEnumerable zawierające elementy typu T2.
Na tej podstawie można łatwo zgadnąć, że ten operator wygeneruje dane wyjściowe, stosując funkcję wejściową do każdego elementu wejściowego IEnumerable i zawijając wyniki do nowego IEnumerable.
Za pomocą matematycznej jak notacji trwa na wejściu (a, b, c, ...) IEnumerable <T1> i f T1 → T2 i wytwarza (F (a), F (b), f (c) , ...): IEnumerable <T2>
Gdzie: (IEnumerable <T1>, Func <T1, bool>) → IEnumerable <T1> ; ten pobiera element IEnumerable zawierający elementy typu T1 i predykat na T1 (to znaczy funkcję, która generuje wynik boolowski dla danych wejściowych typu T1). Widzisz, że dane wyjściowe są również IEnumerable zawierające elementy typu T1.
Tym razem można by się domyślić, że element wejściowy IEnumerable będzie obecny na wyjściu IEnumerable w zależności od wyniku zastosowania predykatu do elementu. Dodając do tego semantykę nazwy operatora, możesz być pewien, że wygeneruje on wynik IEnumerable, pobierając z danych wejściowych tylko te elementy, które są szacowane na true w zastosowaniu predykatu.
Ludzie z doświadczeniem w programowaniu funkcjonalnym zwykle myślą w ten sposób. Pozwala wywnioskować (lub przynajmniej zgadywać ...), co robi operator, tylko patrząc na jego typ!
W ramach ćwiczenia spróbuj spojrzeć na inne operatory wprowadzone przez LINQ na IEnumerables i wydedukować ich zachowanie, zanim przejrzysz dokumentację!
źródło
Są różne:
Select
chodzi o transformację .Where
chodzi o filtrowanie .źródło
Select mapuje wyliczalną do nowej struktury. Jeśli dokonasz wyboru na IEnumerable, otrzymasz tablicę z taką samą liczbą elementów, ale innym typem w zależności od określonego mapowania. Where filtruje IEnumerable, aby uzyskać podzbiór oryginalnego IEnumerable.
źródło
Where
~ = FiltrujSelect
~ = MapaObie wraca
IEnumerable<T>
źródło
Jeśli wiesz, jak zaimplementowali Gdzie i wybierz metody rozszerzeń, możesz przewidzieć, co robi ... Próbowałem zaimplementować gdzie i wybrać metody rozszerzeń ... Możesz na to spojrzeć ...
Gdzie Wdrożenie ::
Wybierz realizację:
Moja implementacja działa dobrze dla każdej kolekcji ... Ale różni się od metod rozszerzeń zaimplementowanych przez Microsoft, ponieważ używają drzew wyrażeń do implementacji tego samego.
źródło
W przypadku Select it możesz zmapować do IEnumerable nowej struktury.
Where () działa jako filtr IEnumerable, zwróci wynik na podstawie klauzuli where.
źródło