2009-12-08 31 views
8

Tengo un IQueryable que está ordenado por alguna condición. Ahora quiero saber la posición de un elemento particular en ese IQueryable. Hay una expresión linq para obtener eso. Diga por ejemplo, hay 10 elementos en la IQueryable y el sexto elemento coincide con una condición, quiero obtener el número 6.Determinar la posición de un elemento en un IQueryable

+1

¿No desea obtener el número 5 si el 6 ° elemento coincide? Normalmente, el primer elemento tiene el índice 0, el segundo tiene el índice 1, etc. –

+0

sí, eso es lo que quería y la respuesta siguiente funciona bien – San

Respuesta

13

Primero seleccione cada elemento con su índice, luego filtrar los artículos, y finalmente extraer el índice original: cama

var result = orderedList 
    .Select((x, i) => new { Item = x, Index = i }) 
    .Where(itemWithIndex => itemWithIndex.Item.StartsWith("g")) 
    .FirstOrDefault(); 

int index= -1; 
if (result != null) 
    index = result.Index; 

prueba:

class Program 
{ 
    static void Main(string[] args) 
    { 
     var orderedList = new List<string> 
     { 
      "foo", "bar", "baz", "qux", "quux", 
      "corge", "grault", "garply", "waldo", 
      "fred", "plugh", "xyzzy", "thud" 
     }.OrderBy(x => x); 

     // bar, baz, corge, foo, fred, garply, grault, 
     // plugh, quux, qux, thud, waldo, xyzzy 
     // Find the index of the first element beginning with 'g'. 

     var result = orderedList 
      .Select((x, i) => new { Item = x, Index = i }) 
      .Where(itemWithIndex => itemWithIndex.Item.StartsWith("g")) 
      .FirstOrDefault(); 

     int index= -1; 
     if (result != null) 
      index = result.Index; 

     Console.WriteLine("Index: " + index); 
    } 
} 

Salida:

Index: 5 
+0

+ 1- Lo hice de la misma manera en mi respuesta. – RichardOD

+0

¿Esta solución genera SQL para todas las operaciones o selecciona todos los elementos de IQueryable y solo después de eso hace que el funcionamiento en la memoria? –

2

Se podría utilizar algo como query.TakeWhile(x => !matchesCondition(x)).Count(), sin embargo, que tiene el efecto de la enumeración de los valores anteriores, que puede no ser lo que quieres

+0

Tienes que enumerar todos los valores precedentes, ¿no? – treaschf

+0

Solución interesante. Sería correcto enumerar los valores anteriores si fuera un objeto de memoria, pero no para un DB. Tenga en cuenta que si el elemento no está en la lista, esta función devuelve la longitud de la lista. Normalmente, usted esperaría que tales funciones retornaran -1 o quizás nulo. –

+0

@Mark Byers: Leí el fraseo de la pregunta como que implica que se sabía que el elemento deseado estaba presente, y solo se deseaba la posición; y el escenario DB era de hecho mi preocupación por enumerar. En la práctica, sospecho que hacer esto a un IQueryable es imprudente, pero como un truco rápido, este enfoque es al menos breve y comprensible. –

0

También puede usar la versión de la función "Dónde" que incluye el índice de recopilación como un parámetro para el predicado fu nction. Vea MSDN para más información.

var result = Enumerable.Range(0, 10).Where((x, i) => i == 6); 

La versión podría dar como resultado una lista vacía si no hay un 6º elemento. Además, esto no evalúa la cláusula where hasta que itere sobre el resultado.

Cuestiones relacionadas