2010-06-16 14 views
10

È possibile avere un'istruzione foreach che attraverserà un oggetto Raccolte in ordine inverso?Come si può invertire la traversata attraverso una collezione C#?

Se non è una dichiarazione foreach, c'è un altro modo?

+3

cringing i commenti e le risposte in questa discussione. Reverse() è * non * un sostituto per un ciclo for(), ha O (n) requisiti di memoria. La scatola nera LINQ può essere pericolosa. –

+0

@Hans: sbagliato. 'Reverse' userà' IList' se disponibile. – SLaks

+1

@SLaks: dove? Non lo vedo –

risposta

18

È possibile utilizzare un normale for ciclo a ritroso, in questo modo:

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

è anche possibile utilizzare LINQ:

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

Tuttavia, il normale for ciclo sarà probabilmente un po 'più veloce.

+2

Il ciclo 'for' può essere più veloce, ma LINQ è sicuramente più chiaro. Preferirei quindi la versione LINQ. – jball

+0

+1 per un metodo di estensione che ho dimenticato! –

+0

Non so perché non mi sono reso conto che potresti attraversare una collezione con parentesi ... quindi suppongo che sia solo per (int i = collections.Count; i> = 0; i -) ... Ugh sono un deficiente. Grazie. –

4

Se si utilizza 3.5, sembra che vi sia un metodo Reverse() in LINQ che non eseguirà l'iterazione in ordine inverso, ma invertirà l'intero elenco, quindi è possibile eseguire il foreach.

Oppure si potrebbe usare una semplice dichiarazione:

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

Stai chiedendo un errore 'IndexOutOfBounds'. Inizia da 'i = count - 1' – Greg

+2

" Non eseguirà iterazione in ordine inverso, ma invertirà l'intera lista. " Questo non è vero. L'iterazione in ordine inverso è * precisamente * cosa fa il metodo di estensione 'Enumerable.Reverse '. Potresti pensare a 'Elenco . Reverse', che [ha lo stesso nome in confusione] (http://stackoverflow.com/questions/2828917/most-awkward-misleading-method-in-the-net-api/2829051 # 2.829.051). –

+0

@Greg, buona cattura, aggiornato. @Dan Tao, stavo pensando alla lista . Reverse. – taylonr

6

Si potrebbe semplicemente chiamare Reverse() sulla raccolta.

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

Non credo ci sia un Reverse() su Collezioni quello è stato il mio primo pensiero. –

+2

@Sam F: È un [metodo di estensione] (http://msdn.microsoft.com/en-us/library/bb383977.aspx) su qualsiasi 'IEnumerable ' (che include 'Raccolta '), disponibile da. NET 3.5 in poi. Vedi [here] (http://msdn.microsoft.com/en-us/library/system.linq.enumerable_methods.aspx) per un elenco di tutti loro. Se usi .NET 3.5 o versioni successive, devi solo aggiungere 'using System.Linq;' all'inizio del tuo file. –

+2

Suppongo che dovrei aggiungere una nota: in modo abbastanza confuso, Reverse() ha un significato diverso per IList rispetto a IEnumerable standard . IList . Reverse() restituisce void in modo che lo snippet funzioni, dovresti dire collection.AsEnumerable(). Reverse(). Affari confusionari, quello – 48klocs

3

In alternativa, se la raccolta è un IEnumerable e quindi senza accesso casuale, utilizzare il metodo di System.Linq IEnumerable.Reverse() e applicare forearch come al solito.

using System.Linq; 

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

L'inversa è l'unica opzione * valida * per l'iterazione inversa su una raccolta. Troppe raccolte non sono indicizzabili. – 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

Problemi correlati