2009-06-25 11 views
50

Sono un novizio LINQ cercando di usarlo per acheive il seguente:Come selezionare i valori all'interno di un intervallo di indice fornito da un elenco utilizzando LINQ

Ho una lista di int: -

List<int> intList = new List<int>(new int[]{1,2,3,3,2,1}); 

Ora, voglio confrontare la somma dei primi tre elementi [intervallo indice 0-2] con gli ultimi tre [intervallo indice 3-5] usando LINQ. Ho provato il LINQ Select e prendere metodi di estensione, nonché il metodo di SelectMany, ma io non riesco a capire come dire qualcosa di simile

(from p in intList 
where p in Take contiguous elements of intList from index x to x+n 
select p).sum() 

Ho guardato il Contiene metodo di estensione troppo, ma che non vede arrivare io quello che voglio Eventuali suggerimenti? Grazie.

risposta

77

Utilizzare Skip quindi Take.

yourEnumerable.Skip(4).Take(3).Select(x=>x) 

(from p in intList.Skip(x).Take(n) select p).sum() 
+6

Nota che List .GetRange sarà più efficiente, anche se per le collezioni più grandi: https: // icodeit. wordpress.com/2012/08/27/performance-of-skip-and-take-in-linq-to-objects/, http://geekswithblogs.net/BlackRabbitCoder/archive/2012/03/29/c.net -little-wonders-skip-and-take.aspx – nawfal

+0

Questo è un commento valido, valido (così valido un paio di anni fa avevo sviato l'autore della risposta di seguito che ha detto la stessa cosa), anche se l'OP ha chiesto specificamente su LINQ così non puoi reall y garantire una lista come fonte. Questa potrebbe essere stata una versione semplificata del vero problema in questione, in cui la versione semplificata era solo una lista codificata (e potrebbe davvero essere una query su un oggetto grafico o una query LINQ su SQL). –

15

Per elenchi più grandi, un metodo di estensione separato potrebbe essere più appropriato per le prestazioni. So che questo non è necessario per il caso iniziale, ma l'implementazione di Linq (sugli oggetti) si basa sull'iterazione dell'elenco, quindi per gli elenchi di grandi dimensioni ciò potrebbe essere (inutilmente) costoso. Un metodo di estensione semplice per raggiungere questo obiettivo potrebbe essere:

public static IEnumerable<TSource> IndexRange<TSource>(
    this IList<TSource> source, 
    int fromIndex, 
    int toIndex) 
{ 
    int currIndex = fromIndex; 
    while (currIndex <= toIndex) 
    { 
     yield return source[currIndex]; 
     currIndex++; 
    } 
} 
+0

Grazie, hai reso la mia giornata! –

26

È possibile utilizzare getRange()

list.GetRange(index, count); 
+1

Dove si trova questa funzione? .NET 4.5 o qualcosa del genere? –

+4

@AdamNofsinger Questo è nello spazio dei nomi System.Collections.Generic. È arrivato con .Net 2.0. http://msdn.microsoft.com/en-us/library/21k0e39c(v=vs.80).aspx – Onuralp

Problemi correlati