في C# .NET 2.0، ما هي الطريقة السهلة لإجراء عملية foreach في الاتجاه المعاكس؟

StackOverflow https://stackoverflow.com/questions/82881

سؤال

لنفترض أن لدي كائن قاموس:

Dictionary myDictionary<int, SomeObject> = new Dictionary<string, SomeObject>();

الآن أريد التكرار عبر القاموس بترتيب عكسي.لا يمكنني استخدام حلقة for البسيطة لأنني لا أعرف مفاتيح القاموس.أ com.foreach سهل:

foreach (SomeObject object in myDictionary.Values)
{
    // Do stuff to object
}

ولكن كيف يمكنني القيام بذلك في الاتجاه المعاكس؟

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

المحلول

سأستخدم SortedList بدلاً من القاموس.لا يزال بإمكانك الوصول إليه عن طريق المفتاح، ولكن يمكنك الوصول إليه عن طريق الفهرس أيضًا.

SortedList sCol = new SortedList();

sCol.Add("bee", "Some extended string matching bee");
sCol.Add("ay", "value matching ay");
sCol.Add("cee", "Just a standard cee");

// Go through it backwards.
for (int i = sCol.Count - 1; i >=0 ; i--)
    Console.WriteLine("sCol[" + i.ToString() + "] = " + sCol.GetByIndex(i));

// Reference By Key
foreach (string i in sCol.Keys)
    Console.WriteLine("sCol[" + i + "] = " + sCol[i]);

// Enumerate all values
foreach (string i in sCol.Values)
    Console.WriteLine(i);

تجدر الإشارة إلى أن القائمة المصنفة تخزن أزواج المفاتيح/القيمة مرتبة حسب المفتاح فقط.

نصائح أخرى

القاموس أو أي شكل آخر من أشكال التجزئة ليس له ترتيب.إذن ما تحاول القيام به لا معنى له :)

إذا كان لديك .NET 3.5، فيمكنك استخدام طريقة الامتداد .Reverse() على IEnumerables.على سبيل المثال:

foeach (SomeObject o in myDictionary.Values.Reverse())
{
     // Do stuff to object
}

في الواقع، في C# 2.0 يمكنك إنشاء مكرر خاص بك يجتاز الحاوية في الاتجاه المعاكس.بعد ذلك، يمكنك استخدام هذا المكرر في بيان foreach الخاص بك.ولكن يجب أن يكون لدى المُكرِّر طريقة للتنقل في الحاوية في المقام الأول.إذا كانت مصفوفة بسيطة، فيمكن أن ترجع إلى الوراء مثل هذا:

static IEnumerable<T> CreateReverseIterator<T>(IList<T> list)
{
    int count = list.Count;
    for (int i = count - 1; i >= 0; --i)
    {
        yield return list[i];
    }
}

لكن بالطبع لا يمكنك فعل ذلك باستخدام القاموس لأنه لا يطبق IList أو يوفر مفهرسًا.القول بأن القاموس ليس به ترتيب غير صحيح:بالطبع لديها النظام.يمكن أن يكون هذا الطلب مفيدًا إذا كنت تعرف ما هو.

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

static void Main(string[] args)
{
    Dictionary<int, string> dict = new Dictionary<int, string>();

    dict[1] = "value1";
    dict[2] = "value2";
    dict[3] = "value3";

    foreach (KeyValuePair<int, string> item in dict)
    {
        Console.WriteLine("Key : {0}, Value: {1}", new object[] { item.Key, item.Value });
    }

    string[] values = new string[dict.Values.Count];
    dict.Values.CopyTo(values, 0);

    foreach (string value in CreateReverseIterator(values))
    {
        Console.WriteLine("Value: {0}", value);
    }

}

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

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

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

for (int i = myCollection.Length - 1; i >= 0; i--)
{
    // do something
}

إذا لم يكن لديك .NET 3.5 وبالتالي طريقة الامتداد العكسي، فيمكنك تنفيذ الطريقة الخاصة بك.أعتقد أنه من المحتمل أن يُنشئ قائمة متوسطة (عند الضرورة) ويكررها في الاتجاه المعاكس، مثل ما يلي:

public static IEnumerable<T> Reverse<T>(IEnumerable<T> items)
{
    IList<T> list = items as IList<T>;
    if (list == null) list = new List<T>(items);
    for (int i = list.Count - 1; i >= 0; i-- )
    {
        yield return list[i];
    }
}

من شأنه أن يكون Dictionary<int, SomeObject> myDictionary, ، وسوف تفعل ذلك عن طريق:

foreach(SomeObject _object in myDictionary.Values.Reverse())
{
}

الطريقة الوحيدة التي يمكنني التوصل إليها نت 2.0 هو نسخ جميع القيم أولاً إلى قائمة، وعكس القائمة ثم تشغيل foreach في تلك القائمة:

Dictionary<int, object> d;
List<object> tmplist;
foreach (object o in d.Values) tmplist.Add(s);
tmplist.Reverse();
foreach (object o in tmplist) {
    //Do stuff
}

إذا كان الترتيب هو الأكثر أهمية، فيمكنك استخدام Stack وإنشاء بنية بسيطة لتخزين زوج الكائنات int الخاص بك.

إذا كنت تريد مجموعة من أنواع القاموس ولكنك تحتاج إلى الحفاظ على ترتيب الإدراج، فيمكنك البحث في KeyedCollectionهنا

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

المشكلة الوحيدة هي أن العنصر الذي يتم تخزينه في المجموعة يجب أن يحتوي على مفتاح int.إذا كان بإمكانك تغيير ذلك إلى سلسلة أو نوع آخر (Guid Mabye).منذ جمع1 سيتم البحث عن مفتاح 1 بدلاً من فهرس 1.

معيار for ستكون الحلقة أفضل.لا داعي للقلق بشأن النفقات العامة للمعالجة لعكس المجموعة.

يمكنك استخدام ال LINQ إلى الكائنات وظيفة Enumerable.Reverse() في .NET 2.0 باستخدام LinqBridge.

الجواب الحرفي:

Dictionary<int, SomeObject>  myDictionary = new Dictionary<int, SomeObject>();

foreach (var pair in myDictionary.OrderByDescending(i => i.Key))
{
    //Observe pair.Key
    //Do stuff to pair.Value
}
foreach (Sample in Samples)

try the following:

Int32 nEndingSample = Samples.Count - 1;

for (i = nEndingSample; i >= 0; i--)
{
     x = Samples[i].x;
     y = Samples[i].y;
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top