ทำไม ToLookup และ GroupBy จึงแตกต่างกัน?


111

.ToLookup<TSource, TKey>ส่งคืนILookup<TKey, TSource>ไฟล์. นอกจากนี้ยังดำเนินการติดต่อILookup<TKey, TSource>IEnumerable<IGrouping<TKey, TSource>>

.GroupBy<TSource, TKey>ส่งคืนIEnumerable<IGrouping<Tkey, TSource>>ไฟล์.

iLookup มีคุณสมบัติตัวทำดัชนีที่ใช้งานง่ายดังนั้นจึงสามารถใช้ในลักษณะเหมือนพจนานุกรม (หรือเหมือนการค้นหา) ในขณะที่ GroupBy ทำไม่ได้ GroupBy โดยไม่มีตัวสร้างดัชนีเป็นความเจ็บปวดในการทำงานด้วย วิธีเดียวที่คุณสามารถอ้างอิงวัตถุส่งคืนได้คือการวนลูปผ่าน (หรือใช้วิธีการขยาย LINQ อื่น) กล่าวอีกนัยหนึ่งในกรณีใด ๆ ที่ GroupBy ทำงาน ToLookup ก็จะทำงานได้เช่นกัน

ทั้งหมดนี้ทำให้ฉันมีคำถามว่าทำไมฉันถึงต้องรำคาญกับ GroupBy? ทำไมจึงควรมีอยู่?


7
GroupByคือIQuerable, ILookupไม่ได้
แมกนัส

5
GroupBy ไม่ได้แจกแจงรายการToLookupในลักษณะเดียวกับ ToList / ToArray
Aducci

3
ฉันได้รับการเสนอชื่อนี้เปิดตั้งแต่คำถามก็ถูกกล่าวหาว่าซ้ำเป็นเรื่องเกี่ยวกับIGroupingมากกว่าGroupByและILookupมากกว่าToLookup ความแตกต่างระหว่างสิ่งเหล่านี้แตกต่างกับความแตกต่างระหว่างสิ่งเหล่านี้ สิ่งนี้ควรชัดเจนจากความแตกต่างในคำตอบระหว่างคำถาม
แซม

1
ทั้งLookupGroupBy
คู่สร้าง

คำตอบ:


175

ทำไมฉันต้องรำคาญกับ GroupBy ทำไมจึงควรมีอยู่?

จะเกิดอะไรขึ้นเมื่อคุณเรียก ToLookup บนวัตถุที่แสดงตารางฐานข้อมูลระยะไกลที่มีแถวเป็นพันล้านแถว

ระบบจะส่งแถวพันล้านแถวและคุณสร้างตารางการค้นหาในเครื่อง

จะเกิดอะไรขึ้นเมื่อคุณเรียก GroupBy บนวัตถุดังกล่าว

สร้างวัตถุแบบสอบถาม ตอนจบของเรื่อง.

เมื่อมีการแจกแจงออบเจ็กต์แบบสอบถามนั้นการวิเคราะห์ตารางจะเสร็จสิ้นบนเซิร์ฟเวอร์ฐานข้อมูลและผลลัพธ์ที่จัดกลุ่มจะถูกส่งกลับตามความต้องการครั้งละสองสามรายการ

เหตุผลคือสิ่งเดียวกัน แต่ผลกระทบด้านประสิทธิภาพของแต่ละอย่างแตกต่างกันอย่างสิ้นเชิง โทร ToLookup หมายความว่าฉันต้องการแคชของสิ่งทั้งหมดในขณะนี้จัดโดยกลุ่ม การเรียก GroupBy หมายถึง "ฉันกำลังสร้างวัตถุเพื่อเป็นตัวแทนของคำถาม 'สิ่งเหล่านี้จะเป็นอย่างไรถ้าฉันจัดเรียงตามกลุ่ม?'"


6
โปสเตอร์ไม่ได้กำหนดเป้าหมายเป็นIQueryable<T>ตัวแทนโดยเฉพาะ คำตอบของคุณครอบคลุมสถานการณ์นั้น แต่เมื่อเป็นเพียง ol ธรรมดาIEnumerable<T>(LINQ-to-Objects) ดูเหมือนว่าไม่มีเหตุผลที่จะใช้อย่างใดอย่างหนึ่งซึ่งเป็นสิ่งที่ฉันเชื่อว่า @Shlomo พยายามที่จะไปถึง ไม่ใช่IQueryable<T>กรณี แต่เป็นกรณี LINQ-to-Objects
casperOne

21
@casperOne: ฉันคิดว่าคุณไม่เข้าใจประเด็นของฉัน แม้ในกรณี LINQ-to-objects การเรียก GroupBy ยังคงไม่วนซ้ำบนคอลเลกชัน (ดังที่ Aducci ชี้ให้เห็นในคำตอบที่คุณลบไป) นั่นคือความแตกต่างพื้นฐาน
Eric Lippert

12
@EricLippert: แต่นั่นเป็นเพียงผลข้างเคียงของการใช้งานหรือมีการรับประกันว่าจะมีการนับจำนวนครั้งเมื่อคุณเรียก ToLookup ไม่ว่าจะมีการเปลี่ยนแปลงอะไรในการใช้งาน

9
@ จะ: คุณเป็นจุดที่ยอดเยี่ยม; เอกสารประกอบไม่ได้รับประกันว่า ToLookup "กระตือรือร้น" ควรสังเกตว่า
Eric Lippert

10
ความกระตือรือร้นอธิบายมัน ภาษาของ 'ToMetaType' ฉันคิดว่าแสดงถึงความกระตือรือร้น แม้ว่าจะเห็นได้ชัดว่าเหลืออยู่ในการใช้งาน 'To' อื่น ๆ ทั้งหมดกระตือรือร้น (ToList, ToArray, ToDictionary) ขอบคุณเพื่อน.
Shlomo

99

ในคำง่ายๆ LINQ-world:

  • ToLookup() - ดำเนินการทันที
  • GroupBy() - การดำเนินการรอการตัดบัญชี

17

ทั้งสองมีความคล้ายคลึงกัน แต่ใช้ในสถานการณ์ที่ต่างกัน .ToLookup()ส่งคืนอ็อบเจ็กต์พร้อมใช้งานที่มีกลุ่มทั้งหมดอยู่แล้ว (แต่ไม่ใช่เนื้อหาของกลุ่ม) โหลดอย่างกระตือรือร้น ในทาง.GroupBy()กลับกันส่งกลับลำดับของกลุ่มที่โหลดแบบขี้เกียจ

ผู้ให้บริการ LINQ ที่แตกต่างกันอาจมีพฤติกรรมที่แตกต่างกันสำหรับกลุ่มที่กระตือรือร้นและขี้เกียจ ด้วย LINQ-to-Object อาจสร้างความแตกต่างเพียงเล็กน้อย แต่ด้วย LINQ-to-SQL (หรือ LINQ-to-EF เป็นต้น) การดำเนินการจัดกลุ่มจะดำเนินการบนเซิร์ฟเวอร์ฐานข้อมูลแทนที่จะเป็นไคลเอนต์ดังนั้นคุณอาจต้องการ ทำการกรองเพิ่มเติมในคีย์กลุ่ม (ซึ่งสร้างHAVINGอนุประโยค) จากนั้นรับเฉพาะบางกลุ่มแทนที่จะเป็นกลุ่มทั้งหมด .ToLookup()ไม่อนุญาตให้ใช้ความหมายดังกล่าวเนื่องจากรายการทั้งหมดถูกจัดกลุ่มอย่างกระตือรือร้น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.