Linq – How to aggregate the results of another query

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 original query. So given the basic example below, is there anyway to combine the 2 linq statements into one? If the original 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 several 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 aggregate way is very interesting and I think have another use for that.

3 thoughts on “Linq – How to aggregate the results of another query

  1. user

    It's relatively tricky, because by the time you've tested whether or not there is an element, you've consumed that first element. I suspect there's a way round it, but it's likely to be a bit hacky… Will think more.

    Reply
  2. user
    ( 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()
    
    Reply
  3. user

    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)
                      });
    
    Reply

Leave a Reply

Your email address will not be published.