Group by في LINQ: 5 أسئلة تزعج المبتدئين

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

Group by في LINQ: فهم التجميع بأمثلة عملية

\n\n

إذا كنت قد كتبت استعلامات على المجموعات في C# ولو مرة واحدة، فبالتأكيد واجهت مهمة: "كيف يمكنني تجميع البيانات؟". موضوع group by in LINQ هو من أكثر المواضيع شيوعًا على Stack Overflow (عشرات الآلاف من المشاهدات). وهذا ليس من قبيل الصدفة: يبدو التجميع بسيطًا فقط للوهلة الأولى. في الواقع، يتعثر المبتدئون في المزالق النموذجية: كيفية اختيار أول سجل في المجموعة، وكيفية حساب المجموع، أو إجراء تجميع متداخل.

\n\n

في هذه المقالة، سنشرح أكثر 5 أسئلة شيوعًا حول LINQ GroupBy ونقدم إجابات عملية. فلنبدأ!

\n\n

1. كيف يعمل GroupBy في LINQ؟ الصيغة الأساسية

\n\n

طريقة GroupBy هي نظير لعامل GROUP BY في SQL. تقوم بتقسيم التسلسل إلى مجموعات بناءً على مفتاح محدد. النتيجة هي مجموعة من كائنات IGrouping<TKey, TElement>، حيث يحتوي كل كائن على المفتاح وجميع العناصر التي تقع في هذه المجموعة.

\n\n

إليك مثال بسيط. لنفترض أن لدينا قائمة بالطلاب:

\n\n
public class Student\n{\n    public string Name { get; set; }\n    public string Group { get; set; }\n    public int Score { get; set; }\n}\n\nvar students = new List<Student>\n{\n    new Student { Name = "آنا", Group = "A", Score = 85 },\n    new Student { Name = "بوريس", Group = "B", Score = 90 },\n    new Student { Name = "فيكا", Group = "A", Score = 78 },\n    new Student { Name = "جليب", Group = "B", Score = 92 }\n};
\n\n

نقوم بالتجميع حسب اسم المجموعة:

\n\n
var grouped = students.GroupBy(s => s.Group);\n\nforeach (var group in grouped)\n{\n    Console.WriteLine($"المجموعة: {group.Key}");\n    foreach (var student in group)\n    {\n        Console.WriteLine($"  {student.Name} — {student.Score}");\n    }\n}
\n\n

النتيجة:

\n
المجموعة: A\n  آنا — 85\n  فيكا — 78\nالمجموعة: B\n  بوريس — 90\n  جليب — 92
\n\n

الأمر بسيط. لكن الشيطان، كما هو الحال دائمًا، يكمن في التفاصيل.

\n\n

2. كيف تختار أول سجل من كل مجموعة؟

\n\n

هذا هو السؤال الأكثر شيوعًا حول group by in LINQ. لنفترض أننا بحاجة للحصول على أفضل طالب من كل مجموعة (بأعلى درجة). كيف نفعل ذلك؟

\n\n

الحل هو الجمع بين GroupBy و First() أو OrderByDescending:

\n\n
var bestStudents = students\n    .GroupBy(s => s.Group)\n    .Select(g => g.OrderByDescending(s => s.Score).First());\n\nforeach (var student in bestStudents)\n{\n    Console.WriteLine($"{student.Name} — {student.Group} — {student.Score}");\n}
\n\n

النتيجة: آنا (85) وجليب (92). لاحظ: داخل Select نقوم بترتيب المجموعة ونأخذ العنصر الأول. هذه هي إجابة سؤال "كيفية عمل LINQ group by first".

\n\n

هام: First() سيؤدي إلى استثناء إذا كانت المجموعة فارغة. إذا كان ذلك ممكنًا، استخدم FirstOrDefault().

\n\n

3. كيف تحسب المجموع، العدد، أو المتوسط لكل مجموعة؟

\n\n

غالبًا بعد التجميع، لا نحتاج فقط إلى تكرار العناصر، بل إلى الحصول على قيم مجمعة. على سبيل المثال، مجموع الدرجات لكل مجموعة أو متوسط الدرجات.

\n\n

نستخدم Sum و Count و Average:

\n\n
var groupStats = students\n    .GroupBy(s => s.Group)\n    .Select(g => new\n    {\n        Group = g.Key,\n        Count = g.Count(),\n        TotalScore = g.Sum(s => s.Score),\n        AverageScore = g.Average(s => s.Score)\n    });\n\nforeach (var stat in groupStats)\n{\n    Console.WriteLine($"المجموعة {stat.Group}: {stat.Count} طلاب، المجموع {stat.TotalScore}، المتوسط {stat.AverageScore:F2}");\n}
\n\n

النتيجة:

\n
المجموعة A: 2 طلاب، المجموع 163، المتوسط 81.50\nالمجموعة B: 2 طلاب، المجموع 182، المتوسط 91.00
\n\n

يمكنك أيضًا استخدام Min و Max — في

المدونات

توصيات الكتب