2010-06-16 7 views
10

¿Es posible tener una instrucción foreach que atraviese un objeto Collections en orden inverso?¿Cómo se puede revertir a través de una colección de C#?

Si no es una declaración foreach, ¿hay alguna otra manera?

+3

Cringing en los comentarios y respuestas en este hilo. Reverse() es * no * un sustituto de un bucle for(), tiene O (n) requisitos de almacenamiento. La caja negra LINQ puede ser peligrosa. –

+0

@Hans: Incorrecto. 'Reverse' usará' IList' si está disponible. – SLaks

+1

@SLaks: ¿dónde? Yo no lo veo –

Respuesta

18

Se puede utilizar un for rizo hacia atrás, de esta manera:

for (int i = collection.Count - 1; i >= 0 ; i--) { 
    var current = collection[i]; 
    //Do things 
} 

También puede utilizar LINQ:

foreach(var current in collection.Reverse()) { 
    //Do things 
} 

Sin embargo, el for rizo probablemente será un poco más rápido.

+2

El bucle 'for' puede ser más rápido, pero el LINQ es ciertamente más claro. Por lo tanto, preferiría la versión LINQ. – jball

+0

+1 por un método de extensión que me olvidé! –

+0

No sé por qué no me di cuenta de que puedes atravesar una colección con corchetes ... así que supongo que es solo para (int i = collections.Count; i> = 0; i -) ... Ugh, soy un idiota. Gracias. –

4

Si está utilizando 3.5, parece que hay un método Reverse() en LINQ que no se repetirá en orden inverso, sino que revertirá toda la lista, entonces podría hacer su foreach.

O usted podría utilizar un simple para la declaración:

for(int i = list.Count -1; i >= 0; --i) 
{ 
    x = list[i]; 
} 
+4

Está pidiendo un error 'IndexOutOfBounds'. Comience en 'i = count - 1' – Greg

+2

" Eso no se repetirá en orden inverso, sino que revertiría la lista completa. " Esto no es cierto. La iteración en orden inverso es * precisamente * lo que hace el método de extensión 'Enumerable.Reverse '. Usted puede estar pensando en 'List .Reverse', que [confusamente tiene el mismo nombre] (http://stackoverflow.com/questions/2828917/most-awkward-misleading-method-in-the-net-api/2829051 # 2829051). –

+0

@Greg, buena captura, actualizada. @Dan Tao, estaba pensando en la lista .Reverse. – taylonr

6

Se podía llamar Reverse() en la colección.

foreach(var item in collection.Reverse()) { ... } 
+0

No creo que haya una inversión() en las colecciones que fue mi primer pensamiento. –

+2

@Sam F: Es un [método de extensión] (http://msdn.microsoft.com/en-us/library/bb383977.aspx) en cualquier 'IEnumerable ' (que incluye 'Colección '), disponible desde. NET 3.5 en adelante. Consulte [aquí] (http://msdn.microsoft.com/en-us/library/system.linq.enumerable_methods.aspx) para obtener una lista de todos ellos. Si usa .NET 3.5 o posterior, solo tiene que agregar 'using System.Linq;' al principio de su archivo. –

+2

Supongo que debería agregar una nota: confusamente, Reverse() tiene un significado diferente para IList que para IEnumerable estándar . IList .Reverse() devuelve nulo, para que mi fragmento funcione, debe decir collection.AsEnumerable(). Reverse(). Negocios confusos, eso. – 48klocs

3

Alternativamente, si la colección es un IEnumerable y por tanto sin acceso aleatorio, utilizar el método de System.Linq IEnumerable.Reverse() y aplicar forearch como de costumbre.

using System.Linq; 

foreach (var c in collection.Reverse()) { 
} 
+0

Invertir es la única opción * viable * para realizar una iteración inversa en una colección. Demasiadas colecciones no son indexables. – Randolpho

2
 List<string> items = new List<string> 
     { 
      "item 1", 
      "item 2", 
      "item 3", 
      "item 4", 
     }; 
     lines.AsEnumerable().Reverse() 
          .Do(a => Console.WriteLine(a), ex => Console.WriteLine(ex.Message),() => Console.WriteLine("Completed")) 
          .Run();   

Reactive Extension for .NET 3.5/4.0

Cuestiones relacionadas