سؤال

أبحث عن حاوية تحافظ على جميع عناصرها مرتبة.لقد نظرت إلى SortedList، لكن ذلك يتطلب مفتاحًا منفصلاً، ولا يسمح بمفاتيح مكررة.يمكنني أيضًا استخدام حاوية غير مصنفة وفرزها بشكل صريح بعد كل إدراج.

الاستخدام:

  • إدراج في بعض الأحيان
  • اجتياز متكرر بالترتيب
  • من الناحية المثالية، لا تعمل مع مفاتيح منفصلة عن الكائن الفعلي، وذلك باستخدام وظيفة المقارنة للفرز.
  • يعد الفرز الثابت للكائنات المكافئة أمرًا مرغوبًا فيه، ولكنه غير مطلوب.
  • الوصول العشوائي غير مطلوب.

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

هل كانت مفيدة؟

المحلول

قد ترغب في إلقاء نظرة على مجموعات الطاقة Wintellect.إنه متاح على CodePlex ويحتوي على عدد لا بأس به من المجموعات المفيدة للغاية.مجموعة OrderedBag الموجودة في المشروع هي بالضبط ما تبحث عنه.يستخدم بشكل أساسي أ شجرة حمراء سوداء لتوفير نوع فعال جداً.

نصائح أخرى

فقط لجعل تعليق إيبار كإجابة، هناك SortedSet<T> منذ .NET 4.0.بالطبع هي مجموعة، مما يعني أنه لا يمكن أن يكون لديك نسخ مكررة.

أود أن أقوم بتوسيع فئة القائمة الخاصة بك، والتي، كما ذكرت، يتم فرزها ببساطة بعد كل إدراج.نظرًا لأن إدخالاتك غير متكررة، فإن نتائج الأداء ستكون ضئيلة، كما أن فرز القائمة التي تم فرزها تقريبًا يكون سريعًا، على أي حال.قم بتوسيع القائمة العامة وتجاوز طريقة الإضافة للفرز على الفور.إذا أصبح الأداء مشكلة، يمكنك إدراجها في مكانها لتوفير بعض الوقت.علاوة على ذلك، يمكنك وضع إدراجاتك في قائمة الانتظار لإجراء عملية إدراج اجتياز واحدة لجميع القيم التي تريد إدراجها.

إذا كنت تريد فقط الالتزام بالمجموعات القياسية، فإن Sort(IComparer<>) وظيفة List<> الطبقة هي الطبقة التي غالبًا ما يتم تجاهلها.كل ما عليك فعله هو إنشاء مناسبة Comparer<> للكائنات الخاصة بك.على سبيل المثال:

public class PositionDateComparer : IComparer<VehiclePosition>
{
    public int Compare(VehiclePosition x, VehiclePosition y)
    {
        if (x.DateTime == DateTime.MinValue)
        {
            if (y.DateTime == DateTime.MinValue)
            {
                // If x is null and y is null, they're
                // equal. 
                return 0;
            }

            // If x is null and y is not null, y
            // is greater. 
            return -1;
        }

        // If x is not null...
        //
        if (y.DateTime == DateTime.MinValue)
        // ...and y is null, x is greater.
        {
            return 1;
        }

        // ...and y is not null, compare the dates
        //
        if (x.DateTime == y.DateTime)
        {
            // x and y are equal
            return 0;
        }

        if (x.DateTime > y.DateTime)
        {
            // x is greater
            return 1;
        }

        // y is greater
        return -1;
    }
}

ثم قم فقط بإجراء vehiclePositionsList.Sort(new PositionDateComparer()) عندما تريد فرز القائمة قبل الوصول إليها.أدرك أن هذا قد لا يكون بهذه البساطة مثل الحاوية التي يتم فرزها تلقائيًا في كل مرة تضيف فيها كائنًا جديدًا، ولكن بالنسبة للكثيرين (مثلي!) قد يكون هذا كافيًا للقيام بالمهمة بنجاح دون الحاجة إلى أي مكتبات إضافية.

كما ذكرت في وقت سابق اليوم هنا, ، ال مكتبة المجموعة العامة C5 لديه الحاوية المناسبة لك.

إذا كان المفتاح أيضًا سمة للكائن، فيمكنك تجربة System.Collections.ObjectModel.KeyedCollection<TKey, TItem>.إنها فئة مجردة، ولكن إذا كان مفتاحك مجرد خاصية للعنصر، فمن السهل جدًا استخلاصها منه.

إليك خدعة قديمة استخدمتها في VB6 لفرز الأشياء أبجديًا:استخدم كائن System.Windows.Forms ListBox، وقم بتعيين الخاصية "Sorted" الخاصة به إلى true.في لغة C#، يمكنك إدراج أي كائن في مربع القائمة، وسيقوم بفرز الكائن أبجديًا حسب قيمة ToString() الخاصة به:

لوحدة الفصل:


باستخدام System.Windows.Forms؛

    static void Main(string[] args)
    {
        ListBox sortedList = new ListBox();
        sortedList.Sorted = true;

        sortedList.Items.Add("foo");
        sortedList.Items.Add("bar");
        sortedList.Items.Add(true);
        sortedList.Items.Add(432); 

        foreach (object o in sortedList.Items)
        {
            Console.WriteLine(o);
        }

        Console.ReadKey();
    }

سيتم عرض هذا:

432
حاجِز
foo
حقيقي

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top