2010-11-12 7 views
7

¡Saludos!¿Cómo hacer una función de "buscar una mejor opción" en LINQ?

Estoy buscando una manera de buscar en una colección el objeto que mejor satisfaga mis criterios. Dado que tengo que hacer esto bastante a menudo, estaba buscando la forma de ejecutar la consulta utilizando LINQ, pero no puedo encontrar una forma sencilla de hacer esto que no "parezca" para perder el tiempo.

Una aplicación funcional sería:

collection.OrderByDescending(f => FitFunction(f)).First()

Pero esto parece hacer innecesaria la clasificación. Realmente solo necesito un escaneo lineal. La función Min LINQ devuelve el mejor ajuste, en lugar del objeto que produce el mejor ajuste, por lo que no parece útil.

Para mayor claridad, el código no LINQ tradicionalmente que iba a escribir (y lo han hecho tantas veces):

T best; 
float bestFit = something very low; 

foreach (T ob in collection) 
{ 
    float fit = FitFunction(ob); 
    if (fit > bestFit) 
    { 
    bestFit = fit; 
    best = ob; 
    } 
} 
return best; 

Y creo que puede simplemente hacer mi propio método de extensión para hacer eso; pero me parece que ya debe haber una forma de hacerlo dentro de LINQ.

Gracias!

+0

en lugar de pasar el objeto 'ob' a' FitFunction', no puede tener el resultado de 'FitFunction' como una propiedad de' ob', habilitando 'collection.Min (t => t.FitValue) ' – vlad

+0

@ vlad: Desafortunadamente, el método Enumerable.Min() devuelve la proyección del valor mínimo ... no la instancia del objeto 't', que es lo que el OP está buscando. Esta es la razón por la cual MoreLINQ presentó los operadores MinBy y MaxBy. – LBushkin

+0

La dificultad es que la función Min produciría 't.FitValue', en lugar de' t'. Aparte de eso, esto necesariamente vincularía FitValue al objeto, lo que evitaría mantener el código débilmente acoplado. –

Respuesta

7

Esto es esencialmente un problema Top-N basado en un predicado con la restricción adicional de que N siempre es igual a 1. Desafortunadamente, no hay un operador integrado LINQ que realice una operación TopN() ... pero como usted señala, no es demasiado difícil escribir uno usted mismo.

La biblioteca MoreLINQ tiene una implementación del operador MaxBy(), que le permite especificar un predicado, y también funcionaría.

+0

El ensamblado 'System.Interactive' que viene con las extensiones reactivas (Rx) también tiene una implementación de' MaxBy'. http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx – bdukes

Cuestiones relacionadas