سؤال

لدي قاموس، شيء من هذا القبيل

Dictionary<Foo,String> fooDict

أتنقل عبر كل شيء في القاموس، على سبيل المثال.

foreach (Foo foo in fooDict.Keys)
    MessageBox.show(fooDict[foo]);

يقوم بذلك بالترتيب الذي تمت به إضافة foos إلى القاموس، لذا فإن العنصر الأول المضاف هو أول foo الذي تم إرجاعه.

كيف يمكنني تغيير الأصل بحيث يكون foo الثالث المضاف، على سبيل المثال، هو foo الثاني الذي تم إرجاعه؟بمعنى آخر، أريد تغيير "الفهرس" الخاص به.

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

المحلول

إذا قرأت الوثائق على MSDN سترى هذا:

"الترتيب الذي يتم به إرجاع العناصر غير محدد."

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

نصائح أخرى

قد تكون مهتمًا بـ OrderedDicationary الطبقة التي تأتي System.Collections.Specialized مساحة الاسم.

إذا نظرت إلى التعليقات في الأسفل، فستجد أن أحد الأشخاص من MSFT قد نشر هذه الملاحظة المثيرة للاهتمام:

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

أعتقد أنه سيكون من السهل الاشتقاق من هذه الفئة وإنشاء نسخة عامة من OrderedDictionary.

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

لماذا أنت مهتم بمعالجة "فهرس" القاموس عندما يكون الغرض منه هو الفهرسة بأنواع عشوائية؟

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

        public void sortSections()
    {
        //OMG THIS IS UGLY!!!
        KeyValuePair<ListViewItem, TextSection>[] sortable = textSecs.ToArray();
        IOrderedEnumerable<KeyValuePair<ListViewItem, TextSection>> sorted = sortable.OrderBy(kvp => kvp.Value.cardinality);

        foreach (KeyValuePair<ListViewItem, TextSection> kvp in sorted)
        {
            TextSection sec = kvp.Value;
            ListViewItem key = kvp.Key;

            textSecs.Remove(key);
            textSecs.Add(key, sec);
        }
    }

الإجابة المختصرة هي أنه لا ينبغي أن يكون هناك طريقة لأن القاموس "يمثل مجموعة من المفاتيح والقيم". وهو ما لا يعني أي نوع من الطلبات.أي اختراق قد تجده يقع خارج نطاق تعريف الفصل وقد يكون عرضة للتغيير.

ربما ينبغي عليك أولاً أن تسأل نفسك ما إذا كان القاموس مطلوبًا حقًا في هذه الحالة، أو ما إذا كان بإمكانك التخلص من استخدام قائمة KeyValuePairs.

خلاف ذلك، شيء من هذا القبيل قد يكون مفيدا:

public class IndexableDictionary<T1, T2> : Dictionary<T1, T2>
{
    private SortedDictionary<int, T1> _sortedKeys;

    public IndexableDictionary()
    {
        _sortedKeys = new SortedDictionary<int, T1>();
    }
    public new void Add(T1 key, T2 value)
    {
        _sortedKeys.Add(_sortedKeys.Count + 1, key);
        base.Add(key, value);
    }

    private IEnumerable<KeyValuePair<T1, T2>> Enumerable()
    {
        foreach (T1 key in _sortedKeys.Values)
        {
            yield return new KeyValuePair<T1, T2>(key, this[key]);
        }
    }

    public new IEnumerator<KeyValuePair<T1, T2>> GetEnumerator()
    {
        return Enumerable().GetEnumerator();
    }

    public KeyValuePair<T1, T2> this[int index]
    {
        get
        {
            return new KeyValuePair<T1, T2> (_sortedKeys[index], base[_sortedKeys[index]]);
        }
        set
        {
            _sortedKeys[index] = value.Key;
            base[value.Key] = value.Value;
        }

    }


}

مع رمز العميل الذي يبدو مثل هذا:

    static void Main(string[] args)
    {
        IndexableDictionary<string, string> fooDict = new IndexableDictionary<string, string>();

        fooDict.Add("One", "One");
        fooDict.Add("Two", "Two");
        fooDict.Add("Three", "Three");

        // Print One, Two, Three
        foreach (KeyValuePair<string, string> kvp in fooDict)
            Console.WriteLine(kvp.Value);



        KeyValuePair<string, string> temp = fooDict[1];
        fooDict[1] = fooDict[2];
        fooDict[2] = temp;


        // Print Two, One, Three
        foreach (KeyValuePair<string, string> kvp in fooDict)
            Console.WriteLine(kvp.Value);

        Console.ReadLine();
    }

تحديث: لسبب ما لن يسمح لي بالتعليق على إجابتي.

على أي حال، IndexableDictionary يختلف عن OrderedDictionary في ذلك

  1. "لا يتم فرز عناصر من طلبات الترتيب بأي شكل من الأشكال." لذلك لن ينتبه Foreach إلى المؤشرات العددية
  2. لقد تمت كتابته بقوة، لذا لا يتعين عليك العبث بإخراج الأشياء من بنيات DictionaryEntry
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top