array c# loops foreach

array - ¿Puedes enumerar una colección en C#fuera de servicio?



foreach list object c# (11)

¿Hay alguna manera de utilizar un ciclo foreach para iterar a través de una colección al revés o en un orden completamente aleatorio?


¿Quieres rand una colección e intentar con ella?

Si es así, intente esto:

Random rand = new Random(Environment.TickCount); test.Sort((string v1, string v2) => { if (v1.Equals(v2)) { return 0; } int x = rand.Next(); int y = rand.Next(); if (x == y) { return 0; } else if (x > y) { return 1; } return -1; }); for (string item in test) { Console.WriteLn(item); } // Note that test is List<string>;


A partir de mi lectura de la Especificación del lenguaje C #, la instrucción de iteración foreach depende de la estructura / clase / interfaz que se itera con la función GetEnumerator () definida. El objeto devuelto por GetEnumerator () debe tener MoveNext () definido como una función miembro. MoveNext () se define como accediendo al "primer" objeto en la lista en su primera llamada, luego al "siguiente" en llamadas subsecuentes, retornando verdadero hasta que no existan más elementos en la lista, en donde devuelve falso.

La característica a la que se refiere Domenic, yield return, aparece por primera vez en la versión 2.0 de la especificación, y parece ser útil para este propósito. Para la versión 1.1, su única opción sería derivar una nueva estructura / clase / interfaz de su base e invalidar GetEnumerator () para devolver un nuevo IEnumerator, donde la función MoveNext () seguiría diferentes reglas para seleccionar el primer elemento de colección y cualquier elemento de colección posterior.

Mi propia recomendación sería usar una colección indexada, luego usar un bucle for con un cálculo de índice apropiado (aquí uno podría usar un generador de números aleatorios si es necesario, con una matriz de enteros u otra técnica para verificar que el mismo valor de índice no es usado dos veces) si tiene que hacer esto en la práctica real.


Como mencionan otras respuestas, el método de extensión Reverse() le permitirá enumerar una secuencia en orden inverso.

Aquí hay un método de extensión de enumeración aleatoria:

public static IEnumerable<T> OrderRandomly<T>(this IEnumerable<T> sequence) { Random random = new Random(); List<T> copy = sequence.ToList(); while (copy.Count > 0) { int index = random.Next(copy.Count); yield return copy[index]; copy.RemoveAt(index); } }

Su uso sería:

foreach (int n in Enumerable.Range(1, 10).OrderRandomly()) Console.WriteLine(n);


De hecho, me gustó el enfoque de cfeduke con LINQ y me molesta que se me haya pasado por la cabeza. Para agregar a mi ejemplo anterior. Si desea hacer las iteraciones par y impar con la ayuda de LINQ, puede usar

// Even foreach (var i in ints.FindAll(number => number % 2 == 0)) { Console.WriteLine(i); } // Odd foreach (var i in ints.FindAll(number => number % 2 != 0)) { Console.WriteLine(i); }


No creo que haya una manera de hacerlo directamente, pero es más o menos as good usar un método de extensión que devuelve una nueva colección a través de la palabra clave yield return . Estos podrían provenir de una biblioteca preexistente; los otros han señalado que LINQ tiene un método Reverse , y cosas como OrderBy también funcionarían.

Ejemplo: si utiliza el método de extensión LINQ Reverse() en IEnumerable<T> , que usa yield return para dar la colección en orden inverso, entonces haciendo un foreach(var myThing in myCollection.Reverse()) se enumerará a través de la colección en orden inverso.

Importante : yield return es la clave. Significa "cuando enumere esta colección, luego vaya a buscar cosas". A diferencia de la alternativa de simplemente construir una nueva colección invertida, que es altamente ineficiente y posiblemente tiene efectos secundarios.


Puede ordenar la Lista suministrando su propio Comparador e iterar sobre ese.


Usando System.Linq podrías hacer ...

// List<...> list; foreach (var i in list.Reverse()) { }

Para un orden aleatorio, debe ordenarlo al azar usando list.OrderBy (otra extensión de Linq) y luego iterar esa lista ordenada.

var rnd = new Random(); var randomlyOrdered = list.OrderBy(i => rnd.Next()); foreach (var i in randomlyOrdered) { }


Utilizando un IList<T> de la Biblioteca de colecciones genéricas C5 , la iteración inversa es una característica, en lugar de la extensión:

foreach (var i in list.Reverse()) { }

Además, puede usar el método Shuffle() para obtener un orden aleatorio:

var listClone = (IList<T>) list.Clone(); listClone.Shuffle(); foreach (var i in listClone) { }


puedes hacerlo al revés:

for (int i=col.count-1; i>0; i--){ DoSomething ( col.item[i]) ; }

No estoy seguro acerca de la sintaxis exacta, pero ese es el paradigma.

En cuanto al orden completamente aleatorio, puede acceder a un elemento de colección a través de su índice. Para asegurarte de que tocas cada elemento, necesitarás hacer un seguimiento de los elementos que ya has procesado (probablemente copiando la colección y luego quitándola después de acceder).

EDITAR: Más detalles para el acceso aleatorio El código para el acceso aleatorio podría verse más o menos así:

collection c = originalCollection; while (c.count > 0) { int i = randomNumber(seed) mod c.count element d = c[i]; c.remove(d); DoSomething(d); }


Usa ordenamiento aleatorio
http://www.dailycoding.com/..using_linq.aspx

List<Employee> list = new List<Employee>(); list.Add(new Employee { Id = 1, Name = "Davolio Nancy" }); list.Add(new Employee { Id = 2, Name = "Fuller Andrew" }); list.Add(new Employee { Id = 3, Name = "Leverling Janet" }); list.Add(new Employee { Id = 4, Name = "Peacock Margaret" }); list.Add(new Employee { Id = 5, Name = "Buchanan Steven" }); list.Add(new Employee { Id = 6, Name = "Suyama Michael" }); list.Add(new Employee { Id = 7, Name = "King Robert" }); list.Add(new Employee { Id = 8, Name = "Callahan Laura" }); list.Add(new Employee { Id = 9, Name = "Dodsworth Anne" }); list = list.OrderBy(emp => Guid.NewGuid()).ToList();


A partir de C # 2.0, es muy fácil utilizar la palabra clave yield para implementar iteradores personalizados. Puede leer más sobre la palabra clave yield en MSDN http://msdn.microsoft.com/en-us/library/9k7k7cf0.aspx

Puede pensar en un rendimiento como la capacidad de devolver un valor desde dentro de un bucle, pero debe consultar el enlace de arriba para obtener una explicación completa de lo que son y lo que pueden hacer.

Escribí un breve ejemplo sobre cómo implementar un par de iteradores personalizados. Los implementé como métodos de extensión ( http://msdn.microsoft.com/en-us/library/bb383977.aspx ) para hacer que el código se alinee un poco más y también utilizo los inicializadores de matriz ( http: // msdn .microsoft.com / en-us / library / aa664573.aspx ) para establecer los valores iniciales para la lista de enteros.

Ni los métodos de extensión ni los inicializadores de matriz son necesarios para implementar iteradores personalizados, pero son buenas características de c # 3.0 que ayuda a escribir código limpio

Aquí están mis ejemplos. Muestra cómo iterar sobre una lista de enteros al solo devolver números impares, números pares, los números invertidos o de una manera completamente aleatoria.

using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { List<int> ints = new List<int> { 1,2,3,4,5,6,7,8,9,10}; Console.WriteLine("Iterating over Odd numbers only."); foreach (int i in ints.Odd()) { Console.WriteLine(i); } Console.WriteLine("Iterating over Even numbers only."); foreach (int i in ints.Even()) { Console.WriteLine(i); } Console.WriteLine("Iterating over the list in reversed order."); foreach (int i in ints.Reversed()) { Console.WriteLine(i); } Console.WriteLine("Iterating over the list in random order."); foreach (int i in ints.Random()) { Console.WriteLine(i); } Console.ReadLine(); } } public static class ListExtensions { /// <summary> /// Iterates over the list only returns even numbers /// </summary> /// <param name="list"></param> public static IEnumerable<int> Even(this List<int> list) { foreach (var i in list) { if (i % 2 == 0) { yield return i; } } } /// <summary> /// Iterates over the list only returns odd numbers /// </summary> public static IEnumerable<int> Odd(this List<int> list) { foreach (var i in list) { if (i % 2 != 0) { yield return i; } } } /// <summary> /// Iterates over the list in reversed order /// </summary> public static IEnumerable<int> Reversed(this List<int> list) { for (int i = list.Count; i >= 0; i--) { yield return i; } } /// <summary> /// Iterates over the list in random order /// </summary> public static IEnumerable<int> Random(this List<int> list) { // Initialize a random number generator with a seed. System.Random rnd = new Random((int)DateTime.Now.Ticks); // Create a list to keep track of which indexes we''ve // already returned List<int> visited = new List<int>(); // loop until we''ve returned the value of all indexes // in the list while (visited.Count < list.Count) { int index = rnd.Next(0, list.Count); // Make sure we''ve not returned it already if (!visited.Contains(index)) { visited.Add(index); yield return list[index]; } } } } }