Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using LINQ to Get Sum/ Average of a List with custom objects

Tags:

c#

linq

I have a class:

public class PointD
{
    public double X
    { get; set; }
    public double Y
    { get; set; }

    public PointD(double x, double y)
    {
        X = x;
        Y=y;
    }
   //operator for +,-, * and / are overridden
 }

Given a list<PointD>, how to get the average of it using LINQ? A for loop equivalent will be something like this:

  double xx, yy;
  for ( int i=0; i< ptlist.Count; i++)
     {
         xx+=ptlist[i].X;
         yy+=ptlist[i].Y; 
     }
  return new PointD(){X=xx, Y=yy};

You can use any built-in LINQ function only. You can't define an extension that takes care of this function.

Any idea?

Edit: Of course, you can use two separate Sum extension method to Sum for X and Y component before merging them. But this is not what I want. What I want is a single query/ method that does the job

like image 221
Graviton Avatar asked Jul 16 '09 07:07

Graviton


2 Answers

The Aggregate function would come in handy here.

var sum = list.Aggregate((acc, cur) => acc + cur);
var average = list.Aggregate((acc, cur) => acc + cur) / list.Count;

Just insure that you have the / operator defined for types PointD and int, and this should do the job.

Note: I'm not quite sure whether you want the sum or average here (your question is somewhat ambiguous about this), but I've included examples for both.

like image 79
Noldorin Avatar answered Sep 18 '22 05:09

Noldorin


You'll need to use the Aggregate method instead so you can provide your own aggregation function (Sum is just a convenient specialized case of this method). Something like:

points.Aggregate(new PointD(0, 0), (a, p) => a + p);

I know you say you don't want any additional methods defined, but if this is a common operation I'd be inclined to write an extension method for this, i.e.

public static PointD Sum(this IEnumerable<PointD> source)
{
    return source.Aggregate(new PointD(0, 0), (a, p) => a + p);
} 

Because it's much more readable to be able to write:

points.Sum();
like image 28
Greg Beech Avatar answered Sep 19 '22 05:09

Greg Beech