tags:

views:

638

answers:

2

Hi,

I want to take the results of a where clause on a list and then take that result set and create just one new type that has all its fields constructed from aggregates of the orginal query. So given the basic example below, is there anyway to combine the 2 linq statements into one? If the orginal where has no rows then it should return null. Thanks!

    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
        }

Update: For my situation, the original set has lots of items but after the where clause the result set is very small. Enumerating over the second set serveral times should not be a problem. Also I need to use first and last on the set to get a value from those records. The group by answer will work best for me. The aggreate way is very interesting and I think have another use for that. Thanks!

+2  A: 
( 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()
Mark Cidade
this works, but be careful with long lists because this will iterate the whole list twice: g.Min() and g.Max(), and so will the original solution.
Lucas
... actually 3 times, first being GroupBy()
Lucas
+8  A: 

This solution iterates the list only once with Aggregate(), but for empty lists it will return the seed value. By the way, the seed values are int.MaxValue and int.MinValue because Math.Min(int.MaxValue, C) will always return C and likewise Math.Max(int.MinValue, C) will always return 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)
                  });
Lucas