اختيار مجموعة
المفاضلات والأداء
اختيار مجموعة درس مجاني في C# Academy على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في C# Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة C# Academy 4 دروس في المجموع.
سؤال واحد أولًا
يبدأ اختيار المجموعة بسؤال واحد: كيف ستصل إلى البيانات؟ حسب الموضع، أم حسب المفتاح، أم ستكتفي بالتحقق من العضوية؟
يجيب كل من List وDictionary وHashSet عن نمط وصول مختلف. طابق الأداة مع النمط، وستبقى شيفرتك سريعة وواضحة.
الوصول حسب الموضع: List
إذا كان الترتيب مهمًا وتصل إلى العناصر باستخدام الفهرس، فاختر List<T>. فهي تحافظ على ترتيب الإدراج وتوفر فهرسة بتكلفة O(1).
من أمثلتها: قائمة خطوات، أو صفوف بترتيب العرض، أو أي تسلسل تكرّر عليه من البداية إلى النهاية. والتكرارات مسموحة.
var steps = new List<string> { "mix", "bake", "cool" };
string first = steps[0]; // O(1) by indexالوصول حسب المفتاح: Dictionary
إذا كنت تبحث عن العناصر باستخدام معرّف فريد، فاختر Dictionary<K,V>. فهو يربط المفتاح بالقيمة بكلفة O(1) في المتوسط.
من أمثلته: معرّف المستخدم بالمستخدم، أو رمز الدولة بالاسم، أو الكلمة بعدد مرات ظهورها. يجيب المفتاح عن سؤال «أي عنصر؟»، بينما تحمل القيمة البيانات.
var users = new Dictionary<int, string> {
[101] = "Ann",
[102] = "Bob"
};
string name = users[101];العضوية والتفرد: HashSet
إذا كان اهتمامك يقتصر على معرفة ما إذا كانت قيمة موجودة، أو كان يجب رفض التكرارات، فاختر HashSet<T>. تبلغ كلفة Contains مقدار O(1) في المتوسط.
من أمثلتها: عناوين URL التي تمت زيارتها، والصلاحيات المسموح بها، والوسوم المميزة. لا توجد قيمة مرتبطة بالعنصر؛ بل يوجد العنصر أو لا يوجد.
var visited = new HashSet<string>();
if (visited.Add(url)) {
// first time seeing this url
}جدول التكاليف
التكاليف المتوسطة: فهرسة List بكلفة O(1)، لكن Contains بكلفة O(n). وتوفر كل من Dictionary وHashSet بحثًا بكلفة O(1).
تبلغ كلفة List.Add في النهاية O(1) مستهلكةً على نحو متوسط؛ أما الإدراج أو الإزالة في الوسط فكلفتهما O(n). وتبلغ كلفة الإضافة والإزالة في Dictionary وHashSet مقدار O(1) في المتوسط.
// List: index O(1), Contains O(n)
// Dictionary: by-key O(1), no index
// HashSet: Contains O(1), no value, no indexاستخدام List.Contains علامة تحذير
يُعد استدعاء list.Contains مرارًا داخل حلقة فخًا بتكلفة O(n تربيع). إذ يفحص كل استدعاء القائمة كاملة.
إذا كانت فحوصات العضوية هي الجزء الأكبر من العمل، فانتقل إلى HashSet. فقد يحول هذا التغيير الواحد حلقةً بطيئة إلى حلقة فورية على البيانات الكبيرة.
using System;
using System.Collections.Generic;
class Program {
static void Main() {
var allow = new HashSet<int> { 2, 4, 6 };
foreach (int n in new[] { 1, 2, 3, 4 })
if (allow.Contains(n)) Console.Write(n + " ");
}
}عندما تحتاج إلى المفتاح والترتيب معًا
هل تحتاج إلى البحث بالمفتاح وإلى ترتيب يمكن التنبؤ به أيضًا؟ لا يضمن Dictionary القياسي الترتيب.
ضع في الاعتبار الاحتفاظ بـ List للترتيب إلى جانب Dictionary للبحث، أو استخدم SortedDictionary<K,V> للمفاتيح المحفوظة بترتيب تصاعدي، مقابل تكلفة O(log n).
var sorted = new SortedDictionary<string, int>();
sorted["b"] = 2;
sorted["a"] = 1;
// enumerates a then b, in key orderمقايضات الذاكرة
تستبدل المجموعات القائمة على التجزئة الذاكرة بالسرعة. يحتفظ كل من Dictionary وHashSet بحاويات داخلية، ويستخدمان ذاكرة أكبر من List أو مصفوفة متراصة.
بالنسبة إلى المجموعات الصغيرة التي تضم بضع قيم، قد يكون فحص List مناسبًا فعلًا ويستخدم ذاكرة أقل. وتظهر فائدة التجزئة على نطاق واسع.
البرمجة باستخدام الواجهات
ينبغي أن تطلب تواقيع الأساليب النوع الأقل تخصيصًا الذي يفي بالغرض. اقبل IEnumerable<T> للقراءة، وIReadOnlyList<T> للقراءة باستخدام الفهرس، وIDictionary<K,V> للوصول حسب المفتاح.
يفصل هذا المستدعين عن اختيارك الملموس، ويتيح لك تبديل التطبيقات لاحقًا دون كسر التواقيع.
int Sum(IEnumerable<int> values) {
int total = 0;
foreach (int v in values) total += v;
return total;
}مثال تطبيقي
يتطلب عدّ الكلمات الفريدة في نص استخدام مجموعتين معًا. يتتبع HashSet الكلمات التي تمت رؤيتها، بينما يحصي Dictionary مرات الظهور.
ينفذ كل منهما مهمة واحدة بإتقان: تفرض المجموعة التفرد، ويربط القاموس الكلمة بتكرارها، وتبلغ تكلفة كلتا العمليتين O(1) في المتوسط.
using System;
using System.Collections.Generic;
class Program {
static void Main() {
var counts = new Dictionary<string, int>();
foreach (var w in "a b a c b a".Split(' '))
counts[w] = counts.GetValueOrDefault(w) + 1;
Console.WriteLine(counts["a"]); // 3
}
}قائمة التحقق لاتخاذ القرار
اطرح الأسئلة بالترتيب: هل أحتاج إلى خريطة من مفتاح إلى قيمة؟ استخدم Dictionary. هل أحتاج فقط إلى التفرد أو العضوية؟ استخدم HashSet.
وإلا، هل أحتاج إلى الترتيب والوصول بالفهرس، مع احتمال وجود تكرارات؟ استخدم List. تغطي قائمة التحقق القصيرة هذه معظم الحالات اليومية.
تحقق سريع
طبّق قائمة التحقق لاتخاذ القرار على حاجة محددة.
مراجعة
اختر حسب نمط الوصول: List للتسلسلات المرتبة المفهرسة؛ وDictionary للبحث من مفتاح إلى قيمة؛ وHashSet للتفرد والعضوية.
راقب Big-O: تجنب List.Contains في الحلقات كثيفة الاستخدام، واستفد من عمليات البحث بالتجزئة بتكلفة O(1)، واكتب البرامج باستخدام الواجهات لتبقى اختياراتك مرنة.
الأسئلة الشائعة
هل درس «اختيار مجموعة» مجاني؟
نعم — نص درس «اختيار مجموعة» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة C# Academy، انتقل إلى CoddyKit PRO. تتضمن دورة C# Academy 4 دروس في المجموع.
ماذا ستتعلم في «اختيار مجموعة»؟
المفاضلات والأداء تتمرن على C# Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ C# Academy؟
لا تُشترط خبرة سابقة. C# Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.
كم من الوقت يستغرق درس «اختيار مجموعة»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس C# Academy هذا؟
نعم. كل درس في C# Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.