Linq: Apa perbedaan antara Select dan Where


122

Metode Selectdan Wheretersedia di Linq. Apa yang harus diketahui setiap pengembang tentang kedua metode ini? Misalnya: kapan harus menggunakan salah satu dari yang lain, keuntungan menggunakan salah satu dari yang lain, dll.


7
Saya tidak berpikir pertanyaan ini harus ditandai sebagai CW, ini mungkin memiliki jawaban yang pasti.
Brandon

1
@Brandon tidak ada salahnya menandai sesuatu CW jika itu objektif.
Rex M

@ Rex, saya setuju. Hanya mengatakan bahwa perbedaan antara Select dan Where memiliki jawaban pasti, dan bagian kedua dari pertanyaan kemungkinan besar akan didasarkan pada praktik yang diterima secara umum. Saya hanya menunjukkannya jika OP tidak yakin tentang menandai sesuatu sebagai CW. Jika dia memang berniat untuk menjadi CW, maka saya tidak keberatan.
Brandon

6
Ada banyak hal yang salah dengan itu. CW tidak berguna, dan menjadi lebih berguna ketika orang menandai pertanyaan secara acak sebagai CW
jalf

Jawaban:


126

Dimana

menemukan item yang cocok dan hanya mengembalikan item yang cocok ( memfilter ).

-> IEnumerable<A>masuk, IEnumerable<A>keluar

Pilih

mengembalikan sesuatu untuk semua item dalam sumber ( proyeksi / transformasi ). Sesuatu itu mungkin item itu sendiri, tetapi lebih biasanya merupakan proyeksi dari beberapa jenis.

-> IEnumerable<A>masuk, IEnumerable<B>keluar


15
Selectakan selalu mengembalikan jumlah elemen yang sama dalam daftar (terlepas dari kondisi filter yang mungkin Anda miliki). Wheredapat mengembalikan lebih sedikit elemen tergantung pada kondisi filter Anda.
goku_da_master

Dan di sini adalah contoh MSDN dari selectdan di sini adalah satu untukwhere
yazanpro

Setidaknya bagi saya, memiliki beberapa latar belakang dengan bahasa lain, ada baiknya untuk berpikir begitu Where == filterdanSelect == map
bgusach

52

Select dan Where adalah dua operator yang sama sekali berbeda yang bekerja pada IEnumerable s.

Yang pertama adalah apa yang kita sebut Operator Proyeksi , sedangkan yang terakhir adalah Operator Pembatasan .

Salah satu cara yang menarik untuk mendapatkan wawasan tentang perilaku operator tersebut adalah dengan melihat "tipe fungsional" mereka.

  • Pilih: (IEnumerable <T1>, Func <T1, T2>) → IEnumerable <T2> ; dibutuhkan sebagai input baik IEnumerable yang mengandung elemen tipe T1 dan fungsi yang mengubah elemen tipe T1 menjadi elemen tipe T2. Outputnya adalah IEnumerable yang mengandung elemen tipe T2.

    Dari sini, orang dapat dengan mudah menebak bahwa operator ini akan menghasilkan outputnya dengan menerapkan fungsi input pada setiap elemen input IEnumerable, dan membungkus hasilnya di dalam IEnumerable baru.

    Menggunakan beberapa notasi seperti matematika, dibutuhkan sebagai input (a, b, c, ...): IEnumerable <T1> dan f: T1 → T2 dan menghasilkan (f (a), f (b), f (c) , ...): IEnumerable <T2>

  • Dimana: (IEnumerable <T1>, Func <T1, bool>) → IEnumerable <T1> ; yang satu ini mengambil IEnumerable yang mengandung elemen tipe T1 dan predikat T1 (yaitu, fungsi yang menghasilkan hasil boolean untuk input tipe T1). Anda melihat bahwa outputnya juga berupa IEnumerable yang mengandung elemen tipe T1.

    Kali ini orang akan menebak bahwa elemen input IEnumerable akan hadir pada output IEnumerable tergantung pada hasil penerapan predikat ke elemen tersebut. Menambahkan ke ini semantik nama operator, Anda dapat yakin bahwa itu akan menghasilkan keluaran IEnumerable dengan mengambil dari masukan satu-satunya elemen yang mengevaluasi ke true pada penerapan predikat.

Orang dengan latar belakang pemrograman fungsional biasanya berpikir seperti ini. Ini memungkinkan Anda untuk menyimpulkan (atau setidaknya menebak ...) apa yang dilakukan operator hanya dengan melihat tipenya!

Sebagai latihan, coba lihat operator lain yang diperkenalkan oleh LINQ pada IEnumerables dan simpulkan perilakunya, sebelum melihat dokumentasinya!


47

Mereka berbeda:

Selectadalah tentang transformasi .

Whereadalah tentang pemfilteran .


18

Pilih peta yang dapat dihitung ke struktur baru. Jika Anda melakukan pemilihan pada IEnumerable, Anda akan mendapatkan larik dengan jumlah elemen yang sama, tetapi jenis yang berbeda tergantung pada pemetaan yang Anda tentukan. Di mana menyaring IEnumerable sehingga memberikan Anda subset dari IEnumerable asli.



7

Jika Anda tahu bagaimana mereka menerapkan Di mana dan memilih metode ekstensi, Anda dapat memprediksi apa yang dilakukannya ... Saya mencoba menerapkan di mana dan memilih metode ekstensi ... Anda dapat melihatnya ...

Dimana Implementasi ::

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

Pilih implementasi ::

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

Implementasi saya berfungsi dengan baik untuk koleksi apa pun ... Tetapi ini berbeda dari metode Ekstensi yang diimplementasikan Microsoft, Karena mereka menggunakan pohon ekspresi untuk menerapkan hal yang sama.


1

Dalam kasus Pilih itu Anda dapat memetakan ke IE yang tak terhitung banyaknya dari struktur baru.

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

Di mana () berfungsi sebagai filter ke IEnumerable, ia akan mengembalikan hasil berdasarkan klausa where.

A.Where(x=>x.uid!=0) //input as [IEnumerable<A>] -------->  return output as [IEnumerable<A> ]
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.