example - En C#.NET 2.0, ¿cuál es una manera fácil de hacer un foreach al revés?
list c# (14)
Digamos que tengo un objeto de diccionario:
Dictionary myDictionary<int, SomeObject> = new Dictionary<string, SomeObject>();
Ahora quiero repetir 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 hacer esto al revés?
Estoy de acuerdo con @leppie, pero creo que mereces 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 a la inversa. 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 "invertir la colección, luego enumerar", pero creo que este es un caso en el que solo tendrás que usar un ciclo "hacia atrás" para:
for (int i = myCollection.Length - 1; i >= 0; i--)
{
// do something
}
Si desea una colección de tipo de diccionario, pero necesita mantener el orden de inserción, puede buscar en KeyedCollection aquí
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 el 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). Como la colección 1 buscará la clave de 1 en lugar del índice de 1.
Si el orden es más importante, podrías apilar y crear una estructura simple para almacenar tu par int, Object.
Si no tiene .NET 3.5 y, por lo tanto, el método de extensión inversa, puede implementar el suyo propio. Supongo que probablemente genere una lista intermedia (cuando sea necesario) y la itere al revés, algo 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];
}
}
Un diccionario o cualquier otra forma de hashtable no tiene orden. Entonces, lo que estás tratando de hacer es inútil :)
Usarí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 clave / valor ordenados por clave solamente.
En realidad, en C # 2.0 puedes crear tu 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 es una matriz simple, podría ir hacia atrás de esta manera:
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 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: Diría que copie los elementos a una matriz, y use el método anterior para recorrerlo en reversa. Me gusta esto:
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 tus valores a una matriz puede parecer una mala idea, pero dependiendo del tipo de valor no es realmente tan malo. ¡Podrías estar copiando referencias!
Eso sería un Dictionary<int, SomeObject> myDictionary
, y lo harías de la siguiente manera:
foreach(SomeObject _object in myDictionary.Values.Reverse())
{
}
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;
}
La única forma en que puedo encontrarme en .NET 2.0 es copiar primero todos los valores en una lista, invertir 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
}
Puede usar la función LINQ to Objects Enumerable.Reverse () en .NET 2.0 utilizando LinqBridge .
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
}
Si tiene .NET 3.5, puede usar el método de extensión .Reverse () en IEnumerables. Por ejemplo:
foeach (SomeObject o in myDictionary.Values.Reverse())
{
// Do stuff to object
}
Un estándar for
bucle sería lo mejor. No tiene que preocuparse por la sobrecarga de procesamiento al invertir la colección.