2014-04-04 11 views
6

Ho un List<string> come:Come trovare il penultimo elemento da un elenco?

List<String> lsRelation = new List<String>{"99","86","111","105"}. 

Ora voglio trovare il numero 111, che è il secondo per ultima stringa.

così ho provato:

String strSecondLast=lsrelation.Last() - 2; 

che non funziona. Quindi, come posso trovare il penultimo elemento di una lista usando Last().

+0

Cosa deve essere restituito se c'è solo un articolo o nessun oggetto? – Caramiriel

+0

@Caramiriel: cosa ti aspetti che un array ritorni se cerchi 'arr [arr.Length]'? Non c'è alternativa a un'eccezione. Ogni valore come 'null' potrebbe essere un valore valido nella raccolta. Quindi non è possibile distinguere tra il caso in cui la raccolta abbia meno di due elementi e il caso in cui l'elemento sia effettivamente 'null'. –

+0

@TimSchmelter: Ci sono vari modi per farlo (eccezione, TryGet-pattern, null se fuori range), anche se volevo solo far scattare la persona a pensare alla possibilità di avere meno di due elementi nella collezione. – Caramiriel

risposta

4

Usa:

if (lsRelation.Count >= 2) 
    secLast = lsRelation[lsRelation.Count - 2]; 
7

Se si sa che è un IList<T> che ha un indicizzatore:

string secondLast = null; 
if (lsRelation.Count >= 2) 
    secondLast = lsRelation[lsRelation.Count - 2]; 

Si potrebbe creare un'estensione come:

public static T SecondLast<T>(this IEnumerable<T> items) 
{ 
    if (items == null) throw new ArgumentNullException("items"); 
    IList<T> list = items as IList<T>; 
    if (list != null) 
    { 
     int count = list.Count; 
     if (count > 1) 
     { 
      return list[count - 2]; 
     } 
     else 
      throw new ArgumentException("Sequence must contain at least two elements.", "items"); 
    } 
    else 
    { 
     try 
     { 
      return items.Reverse().Skip(1).First(); 
     } catch (InvalidOperationException) 
     { 
      throw new ArgumentException("Sequence must contain at least two elements.", "items"); 
     } 
    } 
} 

Quindi è possibile utilizzare in questo modo:

string secondLast = lsRelation.SecondLast(); 
+0

Potrebbe essere utile verificare che l'elenco contenga almeno un elemento item prima di provare '.First()' – CodingIntrigue

+0

@RGraham: Perché? genererà un'eccezione per quel caso che è desiderato. Cosa dovrei restituire, invece? Ogni valore che potrei restituire (come 'default (T)') potrebbe potenzialmente essere un valore valido che sarebbe anche peggio che lanciare un'eccezione significativa. –

+0

@TimSchmelter Un buon punto, non avevo considerato quello – CodingIntrigue

3

Non è possibile farlo utilizzando Last(). Prova questo. Si prende la lunghezza della lista e sottrarre 2:

if (lsRelation.Count >= 2) 
{ 
    var item = lsRelation[lsRelation.Count - 2]; 
} 

Edit:

Sulla base del commento, ecco un esempio utilizzando il metodo Last(), che sarebbe ridicolo da usare:

if (lsRelation.Count >= 2) 
{ 
    var item = lsRelation.Last(x => x == lsRelation[lsRelation.Count - 2]); 
} 
+3

* Non è possibile farlo utilizzando Last() * Non è vero, è possibile utilizzare il sovraccarico del predicato per ultimo e utilizzare l'indice per verificare se è l'ultimo elemento prima dell'indice specificato .... semplicemente non lo fa qualsiasi senso farlo in quel modo :) – CodingIntrigue

+0

@RGraham: hai ragione, controlla la mia risposta aggiornata :) – Abbas

5

È possibile utilizzare ElementAt(list.Count - 2):

List<String> lsRelation = new List<String> { "99", "86", "111", "105" }; 
Console.WriteLine(lsRelation.ElementAt(lsRelation.Count - 2)); // 111 
3

Ci sono un sacco di opzioni per fare questo. Solo per citarne uno che non ho ancora visto:

List<string> lsRelation = new List<String>{"99","86","111","105"}; 
String strSecondLast = lsRelation.Skip(lsRelation.Count()-2).First(); 
Problemi correlati