2010-08-24 10 views

risposta

32

Ci sono diversi modi che si potrebbe fare questo.

  1. Usare un ciclo for invece
  2. Impostare un flag booleano
  3. utilizzare LINQ per ottenere il list.First() e poi sopra foreach list.Skip (1)
18

Qualcosa di simile a questo:

bool first = true; 

foreach(var item in items) 
{ 
    if (first) 
    { 
     item.firstStuff(); 
     first = false; 
    } 
    item.otherStuff(); 
} 
2
bool first = true; 
foreach(var foo in bar) 
{ 
    if (first) 
    { 
    // do something to your first item 
    first = false; 
    } 
    // do something else to the rest 
} 
+0

GRR, non veloce abbastanza! non ho visto il post di geofftnz. – Hamza

+2

è la gara easy-question brevettata StackOverflow :) – geofftnz

+1

ben giocata signore, congratulazioni :) – Hamza

2

Non riesco a pensare ad altro che

var processedFirst = false; 
foreach(var x in items) { 
    if(!processedFirst) { 
     ProcessFirst(x); 
     processedFirst = true; 
    } 
11

Ecco una soluzione performante:

using (var erator = enumerable.GetEnumerator()) 
{ 
    if (erator.MoveNext()) 
    { 
     DoActionOnFirst(erator.Current); 

     while (erator.MoveNext()) 
      DoActionOnOther(erator.Current); 
    } 
} 

EDIT: Ed ecco un LINQ uno:

if (enumerable.Any()) 
    { 
     DoActionOnFirst(enumerable.First()); 

     foreach (var item in enumerable.Skip(1)) 
      DoActionOnOther(item); 
    } 

EDIT: Se le azioni sulle voci hanno firme assegnabili a Func<TItem, TResult>, si può fare:

enumerable.Select((item, index) => index == 0 ? GetResultFromFirstItem(item) : GetResultFromOtherItem(item)); 
+3

Mentre questo tecnicamente soddisfa i requisiti, è significativamente meno leggibile rispetto all'utilizzo di una "prima" bandiera per indicare come altri hanno pubblicato. –

+2

@ Paul: è più efficiente e non vedo perché sia ​​significativamente meno leggibile. – Ani

+0

Non so come sia più efficiente rispetto all'utilizzo di un "primo" flag. – Babar

2

provare questo

bool IsFirst = true; 

foreach(DataRow dr in dt.Rows) 
{ 
    if (IsFirst) 
    { 
     // do some thing 
     IsFirst = false; 
    }  
} 
4

Questa è più di una soluzione generale per ottenere l'indice insieme a ciascun oggetto in una matrice. Dovrebbe funzionare testando se è il primo.

 List<String> entries = new List<string>(); 
     entries.Add("zero"); 
     entries.Add("one"); 
     entries.Add("two"); 

     Dictionary<int, String> numberedEntries = new Dictionary<int, string>(); 
     int i = 0; 
     entries.ForEach(x => numberedEntries.Add(i++, x)); 
     foreach (KeyValuePair<int, String> pair in numberedEntries) { 
      Console.WriteLine(pair.Key + ": " + pair.Value); 
     } 

In questa configurazione, la chiave del KeyValuePair è l'indice e il valore è l'oggetto a tale indice, nel mio esempio una stringa, ma qualsiasi oggetto potrebbe essere collocato lì. Aggiunge un po 'di overhead, ma può essere utilizzato per determinare qualsiasi oggetto nell'indice della lista quando necessario.

+0

Odora come il ditt di Python.__items__ Mi piace! – Hovis

61

Mi piace il modo LINQ, ma senza la Skip (1), in questo modo è anche possibile utilizzarlo per l'ultimo elemento in un elenco e il codice rimane imho pulita :)

foreach(var item in items) 
{ 
    if (items.First()==item) 
     item.firstStuff(); 

    else if (items.Last() == item) 
     item.lastStuff(); 

    item.otherStuff(); 
} 
+5

Non mi piace questo approccio perché non è strettamente accurato. Se un elemento è presente più di una volta, ad esempio, ed è anche il primo o l'ultimo elemento, quindi si attiva la prima o l'ultima condizione più di una volta. o se alcuni oggetti hanno uguaglianza, possono sparare più di una volta. –

+0

@Sahuagin La domanda riguarda il test dell'oggetto per la prima volta o meno. Se cancelli il resto se parte, il che significa che stai testando l'oggetto per essere solo il primo o meno, le tue legittime preoccupazioni saranno lenite. – ErTR

Problemi correlati