วิธีรับบันทึกแรกในแต่ละกลุ่มโดยใช้ Linq


138

พิจารณาบันทึกต่อไปนี้:

   Id          F1            F2             F3 
 -------------------------------------------------
   1           Nima          1990           10
   2           Nima          1990           11
   3           Nima          2000           12
   4           John          2001           1
   5           John          2002           2 
   6           Sara          2010           4

ฉันต้องการจัดกลุ่มตามF1เขตข้อมูลและจัดเรียงIdและรับเขตข้อมูลทั้งหมดจากระเบียนแรกของกลุ่มที่คล้ายกับระเบียนเหล่านี้:

   Id          F1            F2             F3 
 -------------------------------------------------
   1           Nima          1990           10
   4           John          2001           1
   6           Sara          2010           4

ฉันจะทำสิ่งนี้โดยใช้ linq ได้อย่างไร?

คำตอบ:


128
    var res = from element in list
              group element by element.F1
                  into groups
                  select groups.OrderBy(p => p.F2).First();

4
ดีใจมากที่ได้พบสิ่งนี้ ฉันได้รับข้อความแสดงข้อผิดพลาด "วิธีการ 'First' สามารถใช้เป็นการดำเนินการสืบค้นขั้นสุดท้ายเท่านั้นลองใช้วิธี 'FirstOrDefault' ในอินสแตนซ์นี้แทน" จากตัวอย่างของคุณ การดำเนินการเฉพาะในรายการที่ฉันทำหลังจากแบบสอบถามส่ง myResult ToList () ไปยังเมธอด การใช้ FirstOrDefault แก้ไขได้
aghost

จะเป็นOrderBy(p => p.Id)เช่นนั้นหรือไม่พวกเขาต้องการให้เรียงลำดับตาม ID ไม่ใช่คอลัมน์ปี
Mike Flynn

ขอความช่วยเหลือ
หน่อยได้ไหม

จะเป็นอย่างไรหากต้องการดึงรายการแรกและรายการสุดท้ายจากกลุ่ม
Sandeep Pandey

188
var result = input.GroupBy(x=>x.F1,(key,g)=>g.OrderBy(e=>e.F2).First());

3
สิ่งนี้แสดงให้ฉันเห็นวิธีการใช้ไวยากรณ์ของ Fluent การโอเวอร์โหลดของ GroupByดูเหมือนจะทำให้คุณมีพลังมากมาย - หนึ่งในการเพิ่มรายการการเรียนรู้ที่ยาวนาน!
rogersillito

1
@rogersillito ว่าทำไมมันเรียกว่าแบบสอบถาม (Language Integrated Query - LINQ) ยัง GroupBy มีเกินจำนวนมาก แต่มีเพียงความเป็นอยู่ไม่กี่ที่ใช้กันทั่วไปมันก็ขึ้นอยู่กับความชอบส่วนบุคคลเช่นคนบางคนชอบที่จะเขียนมันเป็น.GroupBy(x=>x.F1).Select(g=>...), อาจดูเข้าใจง่ายกว่า
King King

11
คุณควรแทนที่.First()ด้วยมิ.FirstOrDefault()ฉะนั้นคุณจะได้รับข้อยกเว้น:The method 'First' can only be used as a final query operation. Consider using the method 'FirstOrDefault' in this instance instead.
Nikolay Kostov

5
@NikolayKostov ฉันรู้เกี่ยวกับที่ แต่ผมถือว่า LINQ ที่นี่จะใช้เป็น LINQ เพื่อวัตถุไม่ LINQ .First()เพื่อหน่วยงานเพื่อให้เราสามารถได้อย่างปลอดภัยการใช้งาน คำถามของ OP ดูเหมือนแค่ใส่ใจเกี่ยวกับ linq-to-object แม้ว่าเขาจะติดแท็กคำถามด้วยlinq-to-entitiesก็ตาม (ไม่แน่ใจว่าเขาเข้าใจว่าคืออะไร)
King King

1
ฉันชอบคำตอบนี้ Nice one
Ajas Aju

9

awnser ของ @Alireza นั้นถูกต้องทั้งหมด แต่คุณต้องสังเกตว่าเมื่อใช้รหัสนี้

var res = from element in list
          group element by element.F1
              into groups
              select groups.OrderBy(p => p.F2).First();

ซึ่งเหมือนกับรหัสนี้เนื่องจากคุณสั่งซื้อรายการจากนั้นทำการจัดกลุ่มเพื่อให้คุณได้รับแถวแรกของกลุ่ม

var res = (from element in list)
          .OrderBy(x => x.F2)
          .GroupBy(x => x.F1)
          .Select()

ตอนนี้หากคุณต้องการทำสิ่งที่ซับซ้อนมากขึ้นเช่นใช้ผลการจัดกลุ่มเดียวกัน แต่ใช้องค์ประกอบแรกของ F2 และองค์ประกอบสุดท้ายของ F3 หรือสิ่งที่กำหนดเองได้มากขึ้นคุณสามารถทำได้โดยการศึกษาโค้ดร้อง

 var res = (from element in list)
          .GroupBy(x => x.F1)
          .Select(y => new
           {
             F1 = y.FirstOrDefault().F1;
             F2 = y.First().F2;
             F3 = y.Last().F3;
           });

ดังนั้นคุณจะได้รับสิ่งที่ต้องการ

   F1            F2             F3 
 -----------------------------------
   Nima          1990           12
   John          2001           2
   Sara          2010           4

1
ตัวคั่นหรือตัวคั่นของออบเจ็กต์ใหม่ควรเป็นเครื่องหมายจุลภาคไม่ใช่เซมิโคลอนกรุณาตรวจสอบ
Naredla Nithesh Reddy

ส่วนที่ดีคือ. First () และ. Last ()
Somnath Kadam

4

ใช้เพื่อบรรลุสิ่งที่คุณต้องการ จากนั้นตัดสินใจว่าคุณต้องการส่งคืนคุณสมบัติใด

yourList.OrderBy(l => l.Id).GroupBy(l => new { GroupName = l.F1}).Select(r => r.Key.GroupName)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.