Linq: อะไรคือความแตกต่างระหว่าง Select และ Where


122

SelectและWhereวิธีการที่มีอยู่ใน Linq นักพัฒนาทุกคนควรรู้อะไรเกี่ยวกับสองวิธีนี้บ้าง? ตัวอย่างเช่น: เมื่อใดควรใช้อย่างอื่นข้อดีของการใช้อย่างอื่นเป็นต้น


7
ฉันไม่คิดว่าคำถามนี้ควรถูกทำเครื่องหมายเป็น CW แต่อาจมีคำตอบที่ชัดเจน
Brandon

1
@ แบรนดอนไม่มีอะไรผิดปกติในการทำเครื่องหมาย CW บางอย่างหากเป็นวัตถุประสงค์
Rex M

@Rex ฉันเห็นด้วย เพียงแค่บอกว่าความแตกต่างระหว่าง Select และ Where มีคำตอบที่ชัดเจนและส่วนที่สองของคำถามน่าจะมาจากแนวปฏิบัติที่ยอมรับกันทั่วไป ฉันแค่ชี้ให้เห็นในกรณีที่ OP ไม่แน่ใจเกี่ยวกับการทำเครื่องหมายสิ่งต่าง ๆ เป็น CW ถ้าเขาตั้งใจให้มันเป็น CW ฉันก็คงสบายดี
Brandon

6
มีความผิดมากมาย CW จะไม่ได้ผลและได้รับมากขึ้นดังนั้นเมื่อมีคนทำเครื่องหมายคำถามสมบูรณ์ที่สุ่ม CW
jalf

คำตอบ:


126

ที่ไหน

ค้นหารายการที่ตรงกันและส่งคืนเฉพาะรายการที่ทำ (การกรอง )

-> IEnumerable<A>เข้าIEnumerable<A>ออก

เลือก

ส่งคืนบางสิ่งสำหรับรายการทั้งหมดในแหล่งที่มา (การฉายภาพ / การแปลง ) บางสิ่งบางอย่างอาจเป็นของตัวเอง แต่มักจะเป็นการฉายภาพบางประเภท

-> IEnumerable<A>เข้าIEnumerable<B>ออก


15
Selectจะส่งคืนองค์ประกอบจำนวนเท่ากันในรายการเสมอ (ไม่ว่าคุณจะมีเงื่อนไขตัวกรองใดก็ตาม) Whereสามารถคืนค่าองค์ประกอบได้น้อยขึ้นอยู่กับเงื่อนไขตัวกรองของคุณ
goku_da_master

และนี่คือตัวอย่าง MSDN ของselectและนี่คือหนึ่งสำหรับwhere
yazanpro

อย่างน้อยสำหรับฉันมีพื้นฐานภาษาอื่นมาบ้างก็ช่วยให้คิดได้Where == filterและSelect == map
bgusach

52

เลือกและตัวดำเนินการสองตัวที่แตกต่างกันโดยสิ้นเชิงที่ทำหน้าที่บนIEnumerable อยู่ที่ไหน s

ตัวแรกคือสิ่งที่เราเรียกว่าProjection Operatorในขณะที่ตัวสุดท้ายคือไฟล์ผู้ดำเนินการข้อ จำกัด

วิธีหนึ่งที่น่าสนใจในการทำความเข้าใจพฤติกรรมของตัวดำเนินการดังกล่าวคือการดูที่ "ประเภทการทำงาน"

  • เลือก: (IEnumerable <T1>, Func <T1, T2>) → IEnumerable <T2> ; ใช้เป็นอินพุตทั้ง IEnumerable ที่มีอิลิเมนต์ประเภท T1 และฟังก์ชันเปลี่ยนอิลิเมนต์ประเภท T1 เป็นอิลิเมนต์ประเภท T2 เอาต์พุตเป็น IEnumerable ที่มีองค์ประกอบประเภท T2

    จากนี้เราสามารถคาดเดาได้อย่างง่ายดายว่าตัวดำเนินการนี้จะสร้างเอาต์พุตโดยใช้ฟังก์ชันอินพุตกับแต่ละองค์ประกอบของอินพุต IE ที่ไม่สามารถคำนวณได้และรวมผลลัพธ์ไว้ใน IEnumerable ใหม่

    การใช้สัญกรณ์ที่เหมือนคณิตศาสตร์จะใช้เป็นอินพุต(a, b, c, ... ): IEnumerable <T1>และf: T1 → T2และสร้าง(f (a), f (b), f (c) , ... ): IEnumerable <T2>

  • ที่ไหน: (IEnumerable <T1>, Func <T1, bool>) → IEnumerable <T1> ; อันนี้ใช้ IEnumerable ที่มีอิลิเมนต์ประเภท T1 และเพรดิเคตบน T1 (นั่นคือฟังก์ชันที่สร้างผลลัพธ์บูลีนสำหรับอินพุตประเภท T1) คุณจะเห็นว่าเอาต์พุตยังเป็น IEnumerable ที่มีอิลิเมนต์ประเภท T1

    คราวนี้เราจะเดาได้ว่าองค์ประกอบของอินพุต IEnumerable จะมีอยู่ในเอาต์พุต IEnumerable ขึ้นอยู่กับผลลัพธ์ของการประยุกต์ใช้เพรดิเคตกับองค์ประกอบ การเพิ่มความหมายของชื่อตัวดำเนินการนี้คุณสามารถมั่นใจได้ว่าจะสร้างผลลัพธ์ที่ IE ไม่สามารถคำนวณได้โดยรับจากอินพุตเพียงองค์ประกอบเดียวที่ประเมินว่าเป็นจริงในการประยุกต์ใช้เพรดิเคต

ผู้ที่มีการเขียนโปรแกรมเชิงฟังก์ชันพื้นฐานมักจะคิดเช่นนี้ ช่วยให้คุณสามารถอนุมาน (หรืออย่างน้อยก็เดา ... ) ว่าตัวดำเนินการทำอะไรโดยดูจากประเภทเท่านั้น!

ลองดูตัวดำเนินการอื่น ๆ ที่แนะนำโดย LINQ บน IEnumerables และสรุปพฤติกรรมของพวกเขาก่อนที่จะดูเอกสาร!


47

มีความแตกต่างกัน:

Selectเป็นเรื่องเกี่ยวกับการเปลี่ยนแปลง

Whereเป็นเรื่องเกี่ยวกับการกรอง


18

เลือกแมปแจกแจงกับโครงสร้างใหม่ หากคุณทำการเลือกบน IEnumerable คุณจะได้อาร์เรย์ที่มีองค์ประกอบจำนวนเท่ากัน แต่จะเป็นประเภทที่แตกต่างกันขึ้นอยู่กับการแมปที่คุณระบุ โดยที่จะกรอง IEnumerable เพื่อให้คุณเป็นส่วนย่อยของ IEnumerable ดั้งเดิม



7

หากคุณรู้ว่าพวกเขาใช้ที่ไหนและเลือกวิธีการขยายคุณสามารถคาดเดาได้ว่ากำลังทำอะไรอยู่ ... ฉันพยายามนำไปใช้ที่ไหนและเลือกวิธีการขยาย ... คุณสามารถดูได้ ...

สถานที่ดำเนินการ ::

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 คุณสามารถจับคู่โครงสร้างใหม่กับ IE ได้

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

โดยที่ () ทำงานเป็นตัวกรองไปยัง IEnumerable มันจะส่งคืนผลลัพธ์บนพื้นฐานของ where clause

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.