2009-06-25 10 views
50

Yo soy muy novato LINQ tratar de utilizarlo para acheive lo siguiente:Cómo seleccionar valores dentro de un rango de índice proporcionado desde una lista utilizando LINQ

Tengo una lista de enteros: -

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

Ahora, quiero comparar la suma de los primeros tres elementos [rango de índice 0-2] con los últimos tres [rango de índice 3-5] usando LINQ. Probé la LINQ Seleccionar y tomar los métodos de extensión, así como el método SelectMany, pero no puedo encontrar la manera de decir algo como

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

Miré el método de extensión Contiene también, pero que no ve llegar yo lo que quiero ¿Alguna sugerencia? Gracias.

Respuesta

77

Use Skip then Take.

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

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

cuenta que la lista .GetRange será más eficiente, aunque para las colecciones más grandes: 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

Ese es un comentario bueno, válido (tan válido hace un par de años que había votado a favor el autor de la respuesta a continuación que dijo lo mismo), aunque el OP preguntó específicamente sobre LINQ, por lo no puedes reall y garantizar una lista como su fuente. Esto puede haber sido una versión simplificada del problema real en cuestión, donde la versión simplificada era simplemente una lista codificada (y realmente puede ser una consulta en un gráfico de objetos o una consulta LINQ a SQL). –

15

Para listas más grandes, un método de extensión separado podría ser más apropiado para el rendimiento. Sé que esto no es necesario para el caso inicial, pero la implementación de Linq (a los objetos) se basa en la iteración de la lista, por lo que para las listas grandes esto podría ser (sin sentido) costoso. Un método simple extensión para lograr esto podría ser:

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

¡Gracias, has hecho mi día! –

26

Puede utilizar GetRange()

list.GetRange(index, count); 
+1

¿Dónde está esta función? .NET 4.5 o algo así? –

+4

@AdamNofsinger Esto se encuentra en System.Collections.Generic namespace. Venía con .Net 2.0. http://msdn.microsoft.com/en-us/library/21k0e39c(v=vs.80).aspx – Onuralp

Cuestiones relacionadas