การจัดกลุ่มรายการในหน่วยความจำใน C# ด้วย LINQ และนิพจน์ Lambda

เมื่อทำงานกับรายการใน C# คุณอาจพบกับหลายสถานการณ์ที่คุณต้องจัดกลุ่มรายการตามคุณสมบัติที่เฉพาะเจาะจง สำหรับตัวอย่าง สมมติว่าคุณมีคอลเลกชันของวัตถุ Foo และคุณต้องการจัดระเบียบตามค่าของคุณสมบัติ Bar นี่คือจุดที่พลังของ LINQ (Language Integrated Query) และนิพจน์ lambda จะมีบทบาท ในบล็อกโพสต์นี้ เราจะสำรวจวิธีการจัดกลุ่มรายการในหน่วยความจำโดยใช้ฟีเจอร์เหล่านี้ของ C# อย่างมีประสิทธิภาพ

การทำความเข้าใจปัญหา

ลองนึกภาพว่าคุณมีรายการของวัตถุ Foo ซึ่งแต่ละ Foo มีคุณสมบัติ Bar และ Lum บางอินสแตนซ์ของ Foo อาจแชร์ค่าที่เหมือนกันสำหรับ Bar เป้าหมายของคุณคือการจัดกลุ่มอินสแตนซ์ Foo เหล่านี้ตามค่าของ Bar และหลังจากนั้นวนซ้ำผ่านคอลเลกชันที่จัดกลุ่มเพื่อเข้าถึงค่าของ Lum ที่สอดคล้องกัน นี่สามารถปรับปรุงการจัดระเบียบข้อมูลและทำให้สะดวกต่อการจัดการเซ็ตข้อมูลที่เฉพาะเจาะจงมากขึ้น

ตัวอย่างสถานการณ์

ลองพิจารณาตัวอย่างเฉพาะด้วยรายการของอินสแตนซ์ Foo ดังต่อไปนี้:

var foos = new List<Foo> {
   new Foo{Bar = 1,Lum = 1},
   new Foo{Bar = 1,Lum = 2},
   new Foo{Bar = 2,Lum = 3},
};

ผลลัพธ์ที่ต้องการ

เราต้องการจัดกลุ่มอินสแตนซ์ Foo เหล่านี้ตามค่าของ Bar โดยสุดท้ายจะผลิตสิ่งที่คล้ายกับ:

  • สำหรับ Bar = 1: Lum = 1, Lum = 2
  • สำหรับ Bar = 2: Lum = 3

วิธีแก้ปัญหาด้วย LINQ

คุณสามารถจัดกลุ่มวัตถุ Foo โดยใช้คำสั่ง group by ของ LINQ นี่คือวิธีการที่ทำได้:

var groupedFoos = from foo in foos
                  group foo by foo.Bar into grouped
                  let lums = from g in grouped
                             select g.Lum
                  select new { Bar = grouped.Key, Lums = lums };

ขั้นตอนที่อธิบาย

  • Group By: ส่วน group foo by foo.Bar จะจัดกลุ่มอินสแตนซ์ Foo ตามคุณสมบัติ Bar
  • Into Grouped: สิ่งนี้สร้างขอบเขตใหม่สำหรับแต่ละกลุ่ม
  • การเลือกค่า Lum: คำสั่ง let lums ช่วยให้คุณสร้างคอลเลกชันใหม่ที่ประกอบด้วยค่าจากวัตถุที่จัดกลุ่ม
  • การเลือกขั้นสุดท้าย: การเลือกขั้นสุดท้ายจะรวบรวมทุกอย่างเป็นวัตถุใหม่ที่มีค่า Bar และรายการค่าของ Lum ที่สอดคล้องกัน

วิธีแก้ปัญหาด้วยนิพจน์ Lambda

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

var groupedFoos = foos.GroupBy(x => x.Bar)
                      .Select(y => new { Bar = y.Key, Lums = y.Select(z => z.Lum) });

วิธีการทำงาน

  • GroupBy: วิธีนี้รับฟังก์ชัน lambda เพื่อตั้งค่าคุณสมบัติที่เราต้องการจะจัดกลุ่ม โดยเฉพาะอย่างยิ่ง x.Bar
  • Select: หลังจากการจัดกลุ่มแล้ว เราจะใช้ Select เพื่อสร้างวัตถุที่ไม่ระบุชื่อใหม่สำหรับแต่ละกลุ่ม ซึ่งมี Bar และค่าของ Lum ที่สอดคล้องกัน

การวนซ้ำผ่านข้อมูลที่จัดกลุ่ม

ไม่ว่าคุณจะใช้ LINQ หรือนิพจน์ lambda การวนซ้ำผ่านข้อมูลที่จัดกลุ่มยังคงเหมือนเดิม คุณสามารถวนซ้ำแต่ละกลุ่มและพิมพ์ค่าของ Lum ได้ดังนี้:

foreach (var group in groupedFoos)
{
    Console.WriteLine("Lums for Bar#" + group.Bar);
    foreach (var lum in group.Lums)
    {
        Console.WriteLine(lum);
    }
}

เอาท์พุตจะเป็น:

Lums for Bar#1
1
2
Lums for Bar#2
3

บทสรุป

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

สำหรับผู้ที่ต้องการขยายความเข้าใจเกี่ยวกับ LINQ แนะนำให้สำรวจ 101 LINQ Samples เพื่อดูตัวอย่างที่ครอบคลุมเพิ่มเติม

หากคุณมีคำถามหรืออยากจะแบ่งปันประสบการณ์เกี่ยวกับการจัดกลุ่มข้อมูลใน C# โปรดอย่าลังเลที่จะทิ้งความคิดเห็นด้านล่าง!