In C# .NET 2.0, what's an easy way to do a foreach in reverse?

19,336

Solution 1

I'd use a SortedList instead of a dictionary. You can still access it by Key, but you can access it by index as well.

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);

It's worth noting that a sorted list stores key/value pairs sorted by key only.

Solution 2

A dictionary or any other form of hashtable has no ordering. So what you are trying to do is pointless :)

Solution 3

If you have .NET 3.5 you can use the .Reverse() extension method on IEnumerables. For example:

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

Solution 4

Actually, in C# 2.0 you can create your own iterator that traverses a container in reverse. Then, you can use that iterator in your foreach statement. But your iterator would have to have a way of navigating the container in the first place. If it's a simple array, it could go backwards like this:

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

But of course you can't do that with a Dictionary as it doesn't implement IList or provides an indexer. Saying that a Dictionary does not have order is not true: of course it has order. That order can even be useful if you know what it is.

For a solution to your problem: I'd say copy the elements to an array, and use the above method to traverse it in reverse. Like this:

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);
    }

}

Copying your values to an array may seem like a bad idea, but depending on the type of value it's not really that bad. You might just be copying references!

Solution 5

I agree with @leppie, but think you deserve an answer to the question in general. It could be that you meant for the question to be in general, but accidentally picked a bad data structure. The order of the values in a dictionary should be considered implementation-specific; according to the documentation it is always the same order as the keys, but this order is unspecified as well.

Anyway, there's not a straightforward way to make foreach work in reverse. It's syntactic sugar to using the class's enumerator, and enumerators can only travel in one direction. Technically the answer could be "reverse the collection, then enumerate", but I think this is a case where you'll just have to use a "backwards" for loop:

for (int i = myCollection.Length - 1; i >= 0; i--)
{
    // do something
}
Share:
19,336

Related videos on Youtube

Pandincus
Author by

Pandincus

I write code. Sometimes, it works!

Updated on April 16, 2022

Comments

  • Pandincus
    Pandincus about 2 years

    Lets say I have a Dictionary object:

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

    Now I want to iterate through the dictionary in reverse order. I can't use a simple for loop because I don't know the keys of the dictionary. A foreach is easy:

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

    But how can I perform this in reverse?

  • Serhat Ozgel
    Serhat Ozgel over 15 years
    That won't work since the collection that "Values" property of Dictionary class returns, does not have an indexer.
  • Gishu
    Gishu over 15 years
    Use SortedList if you want hashtable type lookups as well as arraylist style sequence ordering. Someone has already posted a code snippet.
  • Orn Kristjansson
    Orn Kristjansson over 12 years
    you will need to reference --> using System.Linq;
  • leppie
    leppie over 12 years
    @DaveVandenEynde: If random is deterministic enough you, I guess.
  • Dave Van den Eynde
    Dave Van den Eynde over 12 years
    Well, my guess is a dictionary is sorted by the hash values. Whether that is useful is an entirely different matter. But random, it is not.