2008-09-17 31 views
16

Digamos que tengo un objeto Dictionary:En C# .NET 2.0, ¿cuál es una manera fácil de hacer un foreach al revés?

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

Ahora quiero recorrer el diccionario en orden inverso. No puedo usar un bucle for simple porque no conozco las teclas del diccionario. Un foreach es fácil:

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

Pero, ¿cómo puedo realizar esta a la inversa?

Respuesta

19

Utilizaría una SortedList en lugar de un diccionario. Aún puede acceder a él mediante Key, pero también puede acceder a él por índice.

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

Vale la pena señalar que una lista ordenada almacena pares de clave/valor ordenados por clave solamente.

28

Un diccionario o cualquier otra forma de hashtable no tiene ningún pedido. Así que lo que estamos tratando de hacer no tiene sentido :)

+0

Oh sí. Duh. Soy completamente estúpido. Gracias :-) – Pandincus

+0

Utilice SortedList si desea búsquedas de tipo hashtable, así como el orden de secuencia de estilo de arrays. Alguien ya ha publicado un fragmento de código. – Gishu

+0

¡Por supuesto que una tabla hash tiene un pedido! –

1

Eso sería un Dictionary<int, SomeObject> myDictionary, y que lo haría por:

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

Si el pedido es más importante, que podría usted una pila y crear una estructura simple para almacenar su int, par de objetos.

18

Si tiene .NET 3.5, puede utilizar el método de extensión .Reverse() en IEnumerables. Por ejemplo:

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

necesitará hacer referencia -> usando System.Linq; –

1

La única manera de que pueda llegar a en .NET 2.0 es copiar primero todos los valores de una lista, revertir la lista y luego ejecutar el foreach en esa lista:

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 
} 
3

Estoy de acuerdo con @leppie, pero creo que merece una respuesta a la pregunta en general. Podría ser que quisieras que la pregunta fuera en general, pero accidentalmente elegiste una mala estructura de datos. El orden de los valores en un diccionario debe considerarse específico de la implementación; de acuerdo con la documentación, siempre es el mismo orden que las teclas, pero este orden no está especificado también.

De todos modos, no hay una manera directa de hacer que foreach funcione en reversa. Es azúcar sintáctico usar el enumerador de la clase, y los enumeradores solo pueden viajar en una dirección. Técnicamente, la respuesta podría ser "revertir la colección, a continuación, enumerar", pero creo que este es un caso en el que sólo tendrá que utilizar un "revés" para el bucle:

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

Eso no funcionará ya que la colección que devuelve la propiedad "Values" de la clase Dictionary no tiene un indexador. –

0

Si quieres una colección de tipo de diccionario pero necesita mantener el orden de inserción que puede buscar en KeyedCollection here

Es una fusión entre un diccionario y una lista. De esta forma, puede acceder a los elementos de la colección a través de la clave o el índice de inserción.

El único problema es si su elemento que se almacena en la colección debe tener una clave int. Si pudieras cambiar eso a una cadena u otro tipo (Guid Mabye). Dado que la colección 1 buscará la clave de 1 en lugar del índice de 1.

0

Un bucle estándar for sería lo mejor. No tiene que preocuparse por la sobrecarga de procesamiento al invertir la colección.

4

En realidad, en C# 2.0 puede crear su propio iterador que atraviesa un contenedor en reversa. Entonces, puedes usar ese iterador en tu declaración de foreach. Pero su iterador debería tener una forma de navegar el contenedor en primer lugar. Si se trata de una matriz simple, se podría ir hacia atrás como esto:

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

Pero por supuesto no se puede hacer eso con un diccionario, ya que no implementa IList o proporciona un indexador. Decir que un diccionario no tiene orden no es cierto: por supuesto que tiene orden. Ese orden incluso puede ser útil si sabes de qué se trata.

Para una solución a su problema: Yo diría copiar los elementos a una matriz, y utilizar el método anterior para recorrerlo en reversa. De esta manera:

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

} 

Copiar sus valores en una matriz que puede parecer una mala idea, pero dependiendo del tipo de valor que en realidad no es tan malo. ¡Podrías estar copiando referencias!

0

respuesta literal:

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 
} 
3

Si usted no tiene .NET 3.5 y por lo tanto el método de extensión inversa puede implementar su propia. Supongo que probablemente genera una lista intermedia (cuando sea necesario) y repite a la inversa, algo así como lo siguiente:

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]; 
    } 
} 
-2
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; 
} 
Cuestiones relacionadas