C# Academy · درس

HashSet والتفرّد

تتبّع القيم المتميزة

الدرس 3 من 413 خطوة

HashSet والتفرّد درس مجاني في C# Academy على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في C# Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة C# Academy 4 دروس في المجموع.

ما هو HashSet؟

يخزن HashSet<T> مجموعةً من القيم الفريدة دون تكرارات. وإضافة قيمة موجودة بالفعل لا تفعل شيئًا ببساطة.

وكما هو الحال في القاموس، يعتمد على جدول تجزئة، ولذلك تبلغ كلفة اختبار العضوية O(1) في المتوسط. ولا يحافظ على ترتيب الإدراج.

using System.Collections.Generic;

var seen = new HashSet<int>();
seen.Add(1);
seen.Add(1); // ignored, still one element

تعيد Add قيمة منطقية

تعيد Add القيمة true إذا كانت القيمة جديدة، وfalse إذا كانت موجودة بالفعل.

تفيد هذه القيمة المعادة في اكتشاف التكرارات في خطوة واحدة، دون إجراء فحص منفصل باستخدام Contains.

using System;
using System.Collections.Generic;

class Program {
    static void Main() {
        var set = new HashSet<string>();
        Console.WriteLine(set.Add("a")); // True
        Console.WriteLine(set.Add("a")); // False
    }
}

اختبارات عضوية سريعة

تبلغ كلفة Contains على HashSet مقدار O(1) في المتوسط، مقارنةً بـ O(n) على List.

عندما تسأل مرارًا «هل رأيت هذه القيمة؟»، تكون المجموعة هي الأداة المناسبة. ويزداد فرق السرعة بشكل كبير كلما كبر حجم المجموعة.

using System;
using System.Collections.Generic;

class Program {
    static void Main() {
        var ids = new HashSet<int> { 10, 20, 30 };
        Console.WriteLine(ids.Contains(20)); // True
        Console.WriteLine(ids.Contains(99)); // False
    }
}

إزالة التكرارات من قائمة

من المهام الشائعة أخذ قائمة والاحتفاظ بالقيم المميزة فقط. ويؤدي إنشاء HashSet من القائمة إلى ذلك بكلفة O(n).

تحتوي المجموعة الناتجة على كل قيمة مرة واحدة. وإذا احتجت إلى قائمة مجددًا، فغلّفها كما يلي: new List<int>(set).

using System;
using System.Collections.Generic;

class Program {
    static void Main() {
        var nums = new List<int> { 1, 2, 2, 3, 3, 3 };
        var unique = new HashSet<int>(nums);
        Console.WriteLine(unique.Count); // 3
    }
}

الاتحاد

يضيف UnionWith كل عنصر من مجموعة أخرى، مع تخطي التكرارات. وتحتوي النتيجة على كل العناصر الموجودة في المجموعتين.

يعدّل هذا العمليةَ المجموعةَ نفسها مباشرةً. وهو أوضح بكثير من التكرار واستدعاء Add لكل عنصر بنفسك.

using System;
using System.Collections.Generic;

class Program {
    static void Main() {
        var a = new HashSet<int> { 1, 2, 3 };
        a.UnionWith(new[] { 3, 4, 5 });
        Console.WriteLine(a.Count); // 5
    }
}

التقاطع

يحتفظ IntersectWith بالعناصر التي تظهر أيضًا في المجموعة الأخرى، ويحذف بقية العناصر.

استخدمه للعثور على العناصر المشتركة، مثل الوسوم المشتركة بين مقالتين أو المستخدمين الموجودين في مجموعتين.

using System;
using System.Collections.Generic;

class Program {
    static void Main() {
        var a = new HashSet<int> { 1, 2, 3, 4 };
        a.IntersectWith(new[] { 2, 4, 6 });
        Console.WriteLine(string.Join(",", a)); // 2,4
    }
}

الفرق

يزيل ExceptWith من المجموعة أي عنصر موجود في المجموعة الأخرى، ويترك العناصر الفريدة للمجموعة.

إنها عملية طرح المجموعات: «العناصر الموجودة في A وليست في B». وهي مفيدة جدًا لحساب ما تغير أو ما تبقى لمعالجته.

var a = new HashSet<int> { 1, 2, 3, 4 };
a.ExceptWith(new[] { 2, 4 });
// a now contains 1 and 3

المجموعة الجزئية والمجموعة الفوقية

يختبر IsSubsetOf وIsSupersetOf علاقات الاحتواء بين المجموعات، ويعيدان قيمة من النوع bool.

يفحص Overlaps ما إذا كان هناك أي عنصر مشترك، بينما يختبر SetEquals ما إذا كانت مجموعتان تحتويان على العناصر نفسها تمامًا بغض النظر عن الترتيب.

var a = new HashSet<int> { 1, 2 };
var b = new HashSet<int> { 1, 2, 3 };
bool sub = a.IsSubsetOf(b);   // true
bool ov = a.Overlaps(b);      // true

مساواة العناصر

يعتمد التفرد على GetHashCode وEquals لنوع العنصر، تمامًا كما هو الحال مع مفاتيح القاموس.

بالنسبة إلى الأنواع المخصصة، أعد تعريف الدالتين كلتيهما أو استخدم record، وإلا فستُعامل كائنان متساويان منطقيًا على أنهما مختلفان، وينتهي كلاهما في المجموعة.

var names = new HashSet<string>(
    System.StringComparer.OrdinalIgnoreCase);
names.Add("Sam");
bool dup = !names.Add("SAM"); // true: treated as same

لا فهرسة ولا ترتيب

لا يتيح HashSet الوصول باستخدام الفهرس؛ فلا يمكنك كتابة set[0]. ويمكنك فقط التكرار عليه باستخدام foreach.

ترتيب التعداد غير مضمون. وإذا احتجت إلى التفرد والترتيب معًا، فاستخدم SortedSet<T>، الذي يحافظ على ترتيب العناصر مقابل عمليات تكلفتها O(log n).

using System;
using System.Collections.Generic;

class Program {
    static void Main() {
        var s = new SortedSet<int> { 3, 1, 2 };
        Console.WriteLine(string.Join(",", s)); // 1,2,3
    }
}

تتبع العناصر التي تمت رؤيتها

من الأنماط الشائعة تصفية تدفق بحيث تظهر كل قيمة مرة واحدة. أضف القيمة إلى مجموعة ونفّذ الإجراء فقط عندما تعيد Add القيمة true.

هذا أوضح وأسرع من فحص قائمة متنامية، إذ يحول فحصًا بتكلفة O(n تربيع) إلى O(n).

using System;
using System.Collections.Generic;

class Program {
    static void Main() {
        var seen = new HashSet<int>();
        foreach (int x in new[] { 1, 1, 2, 3, 2 })
            if (seen.Add(x)) Console.Write(x + " ");
        // prints 1 2 3
    }
}

تحقق سريع

استرجع ما يفرضه HashSet وتكلفة البحث فيه.

مراجعة

يخزن HashSet<T> قيمًا فريدة، مع عمليات إضافة وإزالة واختبار عضوية بتكلفة O(1) في المتوسط، لكنه لا يوفر ترتيبًا أو فهرسة.

يتألق في إزالة التكرارات، وفحوصات «هل رأيت هذه القيمة؟» السريعة، وعمليات جبر المجموعات عبر UnionWith وIntersectWith وExceptWith. وتحتاج أنواع العناصر المخصصة إلى تطبيق صحيح للمساواة.

البدء مجانًا

تعلم C# مع معلم ذكاء اصطناعي — مجانًا

اكتب وقم بتشغيل أكوادك الفعلية في المتصفح، واحصل على مساعدة فورية من معلم ذكاء اصطناعي متاح 24/7، واستمر من حيث توقفت على الويب أو في التطبيق.

الدورات
93
الدروس
346

الأسئلة الشائعة

هل درس «HashSet والتفرّد» مجاني؟

نعم — نص درس «HashSet والتفرّد» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة C# Academy، انتقل إلى CoddyKit PRO. تتضمن دورة C# Academy 4 دروس في المجموع.

ماذا ستتعلم في «HashSet والتفرّد»؟

تتبّع القيم المتميزة تتمرن على C# Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ C# Academy؟

لا تُشترط خبرة سابقة. C# Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.

كم من الوقت يستغرق درس «HashSet والتفرّد»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس C# Academy هذا؟

نعم. كل درس في C# Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. استخدام List عمليًا
  2. البحث في Dictionary
  3. HashSet والتفرّد
  4. اختيار مجموعة
← العودة إلى C# Academy