0Pricing
C# Academy · درس

‏IComparer للفرز المخصّص

وفّروا ترتيبات بديلة باستخدام المقارِنات

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

الفرز بطرق مختلفة

يمتلك النوع ترتيبًا طبيعيًا واحدًا فقط من خلال IComparable<T>. لفرز البيانات نفسها بطرق أخرى، مرّر كائن IComparer<T> أو مفوضًا من النوع Comparison<T> عند موضع الاستدعاء.

تنفيذ IComparer<T>

إن IComparer<T> كائن منفصل يحتوي على أسلوب Compare(x, y). وهو يتبع عقد القيم السالبة والصفر والموجبة نفسه الذي يتبعه CompareTo.

using System;
using System.Collections.Generic;

public class Person
{
    public string Name;
    public int Age;
    public Person(string name, int age) { Name = name; Age = age; }
    public override string ToString() => Name + "(" + Age + ")";
}

public class ByName : IComparer<Person>
{
    public int Compare(Person x, Person y)
        => string.Compare(x.Name, y.Name, StringComparison.Ordinal);
}

public class Program
{
    public static void Main()
    {
        var people = new List<Person> { new Person("Zoe", 1), new Person("Ann", 2) };
        people.Sort(new ByName());
        Console.WriteLine(string.Join(", ", people));
    }
}

مقارنات متعددة لنوع واحد

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

using System;
using System.Collections.Generic;

public class Person
{
    public string Name;
    public int Age;
    public Person(string name, int age) { Name = name; Age = age; }
    public override string ToString() => Name + "(" + Age + ")";
}

public class ByAge : IComparer<Person>
{
    public int Compare(Person x, Person y) => x.Age.CompareTo(y.Age);
}

public class Program
{
    public static void Main()
    {
        var people = new List<Person> { new Person("Ann", 40), new Person("Bo", 20) };
        people.Sort(new ByAge());
        Console.WriteLine(string.Join(", ", people));
    }
}

مفوض Comparison<T>

في عمليات الفرز لمرة واحدة، يكون مفوض Comparison<T>، وغالبًا ما يكون تعبير لامبدا، أكثر اختصارًا من إنشاء فئة كاملة. تقبله List.Sort مباشرةً.

using System;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        var words = new List<string> { "banana", "fig", "apple" };
        // Sort by length using a Comparison<string> lambda
        words.Sort((a, b) => a.Length.CompareTo(b.Length));
        Console.WriteLine(string.Join(", ", words));
    }
}

الفرز التنازلي باستخدام مقارن

اعكس الترتيب بتبديل المعاملين داخل Compare. وبذلك تحصل على فرز تنازلي من دون تعديل النوع نفسه.

using System;
using System.Collections.Generic;

public class DescendingInt : IComparer<int>
{
    public int Compare(int x, int y) => y.CompareTo(x);
}

public class Program
{
    public static void Main()
    {
        var nums = new List<int> { 3, 1, 4, 1, 5 };
        nums.Sort(new DescendingInt());
        Console.WriteLine(string.Join(", ", nums));
    }
}

المقارنات في OrderBy

يقبل OrderBy في LINQ كائنًا من النوع IComparer<TKey> كوسيط ثانٍ، مما يتيح لك تخصيص طريقة مقارنة المفاتيح المحددة.

using System;
using System.Collections.Generic;
using System.Linq;

public class CaseInsensitive : IComparer<string>
{
    public int Compare(string x, string y)
        => string.Compare(x, y, StringComparison.OrdinalIgnoreCase);
}

public class Program
{
    public static void Main()
    {
        var names = new[] { "bob", "Alice", "carol" };
        foreach (var n in names.OrderBy(x => x, new CaseInsensitive()))
            Console.WriteLine(n);
    }
}

المقارنة متعددة المفاتيح

يمكن للمقارن الفرز حسب عدة مفاتيح وفق ترتيب الأولوية. احسب المفتاح الأول، وإذا حدث تعادل فانتقل إلى المفتاح التالي.

using System;
using System.Collections.Generic;

public class Employee
{
    public string Dept;
    public int Salary;
    public Employee(string dept, int salary) { Dept = dept; Salary = salary; }
    public override string ToString() => Dept + ":" + Salary;
}

public class ByDeptThenSalary : IComparer<Employee>
{
    public int Compare(Employee x, Employee y)
    {
        int byDept = string.Compare(x.Dept, y.Dept, StringComparison.Ordinal);
        return byDept != 0 ? byDept : x.Salary.CompareTo(y.Salary);
    }
}

public class Program
{
    public static void Main()
    {
        var staff = new List<Employee>
        {
            new Employee("IT", 50), new Employee("HR", 40), new Employee("IT", 30)
        };
        staff.Sort(new ByDeptThenSalary());
        Console.WriteLine(string.Join(", ", staff));
    }
}

اختصار Comparer.Create

ينشئ Comparer<T>.Create كائنًا من النوع IComparer<T> انطلاقًا من تعبير لامبدا، جامعًا بين اختصار المفوض وواجهات API التي تتطلب مقارنًا.

using System;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        var byLengthDesc = Comparer<string>.Create((a, b) => b.Length.CompareTo(a.Length));
        var words = new List<string> { "hi", "hello", "hey" };
        words.Sort(byLengthDesc);
        Console.WriteLine(string.Join(", ", words));
    }
}

إعادة استخدام المقارنات عبر المجموعات

يمكن لمثيل مقارن واحد تنفيذ الفرز والبحث والمجموعات المرتبة. ويساعد تعريفه مرة واحدة على الحفاظ على اتساق قواعد الترتيب في جميع مواضع استخدامه.

using System;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        IComparer<int> desc = Comparer<int>.Create((a, b) => b.CompareTo(a));
        var set = new SortedSet<int>(desc) { 1, 5, 3 };
        Console.WriteLine(string.Join(", ", set));
    }
}

اختيار IComparable أم IComparer

استخدم IComparable<T> للترتيب الطبيعي الوحيد المضمّن في النوع. واستخدم IComparer<T> أو Comparison<T> للترتيبات البديلة المتعددة الخاصة بالسياق، والتي تحددها عند موضع الاستدعاء.

using System;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        var nums = new List<int> { 5, 2, 8, 1 };
        nums.Sort(); // natural ascending (int is IComparable)
        Console.WriteLine(string.Join(", ", nums));
        nums.Sort((a, b) => b - a); // custom descending via delegate
        Console.WriteLine(string.Join(", ", nums));
    }
}

جرّب بنفسك

افرز قائمة واحدة بثلاث طرق مختلفة باستخدام المقارنات وتعبير لامبدا، من دون لمس نوع العناصر.

using System;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        var words = new List<string> { "pear", "fig", "apple", "kiwi" };

        words.Sort(); // natural alphabetical
        Console.WriteLine(string.Join(", ", words));

        words.Sort((a, b) => a.Length.CompareTo(b.Length)); // by length
        Console.WriteLine(string.Join(", ", words));

        words.Sort(Comparer<string>.Create((a, b) => b.CompareTo(a))); // reverse alphabetical
        Console.WriteLine(string.Join(", ", words));
    }
}

تحقق سريع

اختر تجريد الترتيب المناسب.

مراجعة

يستخدم الفرز المخصص مقارنات تُمرر عند موضع الاستدعاء.

  • ينفذ IComparer<T> الأسلوب Compare(x, y) وفق عقد القيم السالبة والصفر والموجبة.
  • تناسب مفوضات Comparison<T> وتعبيرات لامبدا عمليات الفرز لمرة واحدة.
  • يربط Comparer<T>.Create تعبيرات لامبدا بالواجهة.
  • استخدم IComparable للترتيب الطبيعي، والمقارنات للترتيبات البديلة.

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

هل درس «‏IComparer للفرز المخصّص» مجاني؟

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

ماذا ستتعلم في «‏IComparer للفرز المخصّص»؟

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

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

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

كم من الوقت يستغرق درس «‏IComparer للفرز المخصّص»؟

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

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

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

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

  1. تنفيذ IEquatable
  2. تجاوز GetHashCode
  3. تنفيذ IComparable
  4. ‏IComparer للفرز المخصّص
← العودة إلى C# Academy