LINQ - Cómo agregar los resultados de otra consulta
Pregunta
Quiero aprovechar los resultados de una cláusula where en una lista y luego tomar ese conjunto de resultados y crear sólo un nuevo tipo que tiene todos sus campos construidos a partir de agregados de la consulta original. Así que dado el ejemplo básico de abajo, hay alguna forma de combinar las declaraciones 2 LINQ en una sola? Si el original donde tiene ninguna fila, entonces debería devolver null. Gracias!
class Foo
{
public int A { get; set; }
public int B { get; set; }
}
List<Foo> lst = GetFooList();
var q = (from f in lst
where f.A > 3
select f).ToList();
if (q.Count != 0)
{
var qq = new
{
MinA = q.Min(l => l.A),
MaxB = q.Max(h => h.B),
};
// now do something with qq
}
Actualización: Para mi situación, el conjunto original tiene un montón de artículos, pero después de la cláusula en el que el conjunto de resultados es muy pequeño. Enumerando sobre el segundo set en varias ocasiones no debería ser un problema. También tengo que usar primero y el último en el set para obtener un valor de esos registros. El grupo de respuesta que funciona mejor para mí. La forma agregada es muy interesante y creo que tienen otro uso para eso.
Solución
( from f in GetFooList()
where f.A > 3
group f by 1 into g
let MinA=g.Min(l=>l.A)
let MaxB=g.Max(h=>h.B)
select new {MinA, MaxB} ).SingleOrDefault()
Otros consejos
Esta solución itera la lista sólo una vez con Aggregate()
, pero para las listas vacías se devolverá el valor de la semilla. Por cierto, los valores de semillas son int.MaxValue
y int.MinValue
porque Math.Min(int.MaxValue, C)
siempre devolverá C y del mismo modo Math.Max(int.MinValue, C)
siempre devolverá C.
var b = lst.Where(f => f.A > 3)
.Aggregate(
// seed, initial values
new
{
MinA = int.MaxValue,
MaxB = int.MinValue
},
// accumulator function
(a,f) => new
{
MinA = Math.Min(a.MinA , f.A),
MaxB = Math.Max(a.MaxB , f.B)
});