Edit: This is an example program, I understand that there is a sum operator in linq. However, I was trying to ask specifically on how to pass the pointer to the property to do something complex with it, not necessarily this summing algorithm.
Lets say I have a class like this:
class Point
{
double x {get; set;}
double y {get; set;}
}
and in my main program I had 2 functions.
double function1(List<Point> PointList)
{
double sum = 0.0;
foreach(Point p in PointList)
{
sum += p.x;
}
return sum;
}
double function2(List<Point> PointList)
{
double sum = 0.0;
foreach(Point p in PointList)
{
sum += p.y;
}
return sum;
}
These functions are completely identical except one is summing the X values, the other is summing the Y values. Since these are so similar, I would like to combine them such that I basically pass in that List of Points, and something to identify that I want to do the X or the Y based calculation.
I know I could put in a switch statement and tell it whether it was the X or the Y based on an enum, or a number that is defined to tell it to do the X or the Y. If this was a normal function, I suppose I could use s delegate, but this is a property, so I'm not sure how that translates.
So how do I combine those functions into something like:
double bothFunctions(List<Point> PointList, var propertyToUse)
{
double sum = 0.0;
foreach(Point p in PointList)
{
sum += p.propertyToUse;
}
return sum;
}
Where propertyToUse points to either X or Y.
The current solutions work great, but they assume either that your operation is sum, or that you will have only two possible properties (X and Y).
If you want more freedom, you can do:
double function(List<Point> PointList, Func<Point, double> selector)
{
double sum = 0.0;
foreach (Point p in PointList)
{
sum += selector(p);
}
return sum;
}
Then you call it like this:
double sumX = function(PointList, p => p.X);
double sumY = function(PointList, p => p.Y);
you'll be able to write more complicated selectors, like:
double sumXY = function(PointList, p => p.X + p.Y);
You should look at using the Enumerable.Sum extension method instead of writing your own.
var sumX = pointList.Sum(item => item.X);
var sumY = pointList.Sum(item => item.Y);
You will need to add using System.Linq; if not already present in your code file.
I think you're making it too complicated. You can use a method like this:
double bothFunctions(List<Point> PointList, bool sumX)
{
double sum = 0.0;
foreach(Point p in PointList)
{
if (sumX)
sum += p.x;
else
sum += p.y;
}
return sum;
}
Or just use LINQ:
var ySum = pointList.Sum(e => e.y);
var xSum = pointList.Sum(e => e.x);
Related
I have a Listof points and I want to calculate the remaining distance to the end using Linq (given an index):
double remainingToEnd = Points.Skip(CurrentIndex).Aggregate((x, y) => x.DistanceTo(y));
This doesn't compile:
Cannot convert lambda expression to intended delegate type because
some of the return types in the block are not implicitly convertible
to the delegate return type
I normally solve this situation projecting by using the Select extension, but that would prevent me from calculating the distance afterwards.
This is easily achieved by using a loop but I want to know if it is possible with some simple Linq. I would like to avoid anonymous types too.
Point is defined like:
public class Point
{
public float X { get; set; }
public float Y { get; set; }
public float Z { get; set; }
public float DistanceTo(Point p2)
{
float x = this.X - p2.X;
float y = this.Y - p2.Y;
float z = this.Z - p2.Z;
return (float)Math.Sqrt((x * x) + (y * y) + (z * z));
}
}
Assume you want to calculate total distance between points in collection (starting from some index). You need previous point on each step. You can get it by zipping points collection with itself:
double remainingToEnd = Points.Skip(CurrentIndex)
.Zip(Points.Skip(CurrentIndex + 1), (x,y) => x.DistanceTo(y))
.Sum();
Zip will produce pairs of starting and ending points. Result selector function will select distance between points for each pair. And then you just calculate sum or distances.
You can solve this task with aggregation as will, but you need to store last point on each step. So you need accumulator which will keep both current distance and last point:
var remainingToEnd = Points.Skip(CurrentIndex).Aggregate(
new { total = 0.0, x = Points.Skip(CurrentIndex).FirstOrDefault() },
(a, y) => new { total = a.total + a.x.DistanceTo(y), x = y },
a => a.total);
And keep in mind, that Skip means just iterating your sequence item by item without doing anything. If you have a lot of points, skipping twice can hurt your performance. So if you have list of points, and performance matters, then simple for loop will do the job:
double remainingToEnd = 0.0;
for(int i = CurrentIndex; i < Points.Count - 1; i++)
remainingToEnd += Points[i].DistanceTo(Points[i+1]);
Try this:
double remainingToEnd = Points.Skip(CurrentIndex).Sum(point => point.DistanceTo(Points[Points.Findindex(p => p == point) - 1]));
As an example, I have a type like this:
public class Stuff
{
public Double StuffAmount;
public String StuffDescription;
public DateTime StuffDate;
}
I need to check for things like standard deviation, and I've found those solutions elsewhere on stackoverflow. But to do them the way they're being proposed, I would need to do something like this:
List<Double> stuffAmounts = new List<Double>();
foreach (var s in List<Stuff>)
{
stuffAmounts.Add(s.StuffAmount);
}
//now I have a list of doubles that I can do frequently referenced math functions with
Is there anyway to do something like this without having to make a new list, just using my complex type that already has the doubles as properties?
You can do some of the following
Solution 1
As discussed you can just Select into the appropriate type and pass it to your StandardDeviation method
Given
public static double StandardDeviation(List<double> valueList)
{
double M = 0.0;
double S = 0.0;
int k = 1;
foreach (double value in valueList)
{
double tmpM = M;
M += (value - tmpM) / k;
S += (value - tmpM) * (value - M);
k++;
}
return Math.Sqrt(S / (k-2));
}
Usage
List<Double> stuffAmounts = myListOfStuff.Select(s => s.StuffAmount).ToList()
double result = StandardDeviation(stuffAmounts);
Solution 2
Or you could create an extension method and put your standard math calculations in the one place
Given
public static class MathExtensions
{
public static double StandardDeviation<T>(this List<T> list, Func<T, Double> selector) where T : class
{
var m = 0.0;
var s = 0.0;
var k = 1;
foreach (var value in list.Select(selector))
{
var tmpM = m;
m += (value - tmpM) / k;
s += (value - tmpM) * (value - m);
k++;
}
return Math.Sqrt(s / (k - 2));
}
}
Usage
var stuffs = new List<Stuff>();
var result = stuffs.StandardDeviation(x => x.StuffAmount);
From your question I'm not 100% certain this is what you want but it seems to me all you want is to not create a second list and to do this you just need to pass the original list as a parameter and access the appropriate property where you want. Something like the below
Given
public static double StandardDeviation(List<Stuff> valueList)
{
double M = 0.0;
double S = 0.0;
int k = 1;
foreach (var value in valueList)
{
double tmpM = M;
M += (value.StuffAmount - tmpM) / k;
S += (value.StuffAmount - tmpM) * (value.StuffAmount - M);
k++;
}
return Math.Sqrt(S / (k - 2));
}
Usage
double stdDev = StandardDeviation(data)
I have an array of numbers(double) and I want to implement a recursive method in C# to calculate a running average for a given position in the array using the following algorithm:
µn+1 = (n * µn)/(n+1) + Xn+1/n
where µn+1 is the average at the position I'm interested in,
µn is the average of the prior iteration and Xn+1 is the nth element of the array.
I have been able to do it with an averaging function and an iterative function but not recursion:
static double Flow(double[] A, int n)
{
double U = (A[0] + A[1]) / 2.0;
if (n == 2) { return U; }
else if (n == 1) { return A[0]; }
else
{
for (int i = 3; i <= n; i++)
{
U = Avg(A, U, i);
}
}
return U;
}
static double Avg(double[] A, double M, int n)
{
double a =(n - 1) * M / (n);
double b = A[n - 1] / (n);
return a + b;
}
You need to define µ1, whatever your initial value of the first average is, for your algorithm to work. Also, variable i is not involved in your expression so what's it? Since Xn+1 is divided by n, I presume it can't be zero. Then the function should look like this:
double Avg(double[] array, int n)
{
if (n = 2)
{
return u1/2+array[2]; //u1 is a set value.
}
return (n-1)*Avg(array, n-1)/n+array[n]/(n-1);
}
Last but not least, it's more convenient to express recursive algorithm in µn = ... µ(n-1) instead of µ(n+1)=...µn.
Having an object that has as a double[6] array property as its geometric bounds:
"xmin: " << bounds[0]
"xmax: " << bounds[1]
"ymin: " << bounds[2]
"ymax: " << bounds[3]
"zmin: " << bounds[4]
"zmax: " << bounds[5]
While iterating several objects and getting this property
I want to store the greatest value of xmax,ymax,zmax of all iterated objects
What would be the best way to accomplish this task, I have this idea, however I would like to use Linq
double[] max = new double[6];
double xmax = 0.0;
double ymax = 0.0;
double zmax = 0.0;
foreach (var o in myObject)
{
max = o.bounds;
if (xmax < max[1])
{
xmax = max[1];
}
if (ymax < max[3])
{
ymax = max[3];
}
if (zmax < max[5])
{
zmax = max[5];
}
}
You can do it using Enumerable.Max method:
double xmax = myObject.Select(x => x.bounds[1]).Max();
double ymax = myObject.Select(x => x.bounds[3]).Max();
double zmax = myObject.Select(x => x.bounds[5]).Max();
Note that this solution enumerates the collection three times unnecessarily.Your foreach loop is enumerates the collection only once, if I were you I would keep using the simple loop and use LINQ only when it's helpful.But ofcourse the decision is up to you.If your collection is not noticeably huge, you can prefer the more readable approach.
I would go with this approach:
double xmax = myObject.Max(mo => mo.bounds[1]);
double ymax = myObject.Max(mo => mo.bounds[3]);
double zmax = myObject.Max(mo => mo.bounds[5]);
This produces very fast results.
If you want to iterate the enumerable only once using linq, then do it this way:
var max = myObject
.Select(mo => mo.bounds)
.Aggregate(
new { x = double.MinValue, y = double.MinValue, z = double.MinValue },
(a, b) => new
{
x = Math.Max(a.x, b[1]),
y = Math.Max(a.y, b[3]),
z = Math.Max(a.z, b[5]),
});
While this is only one iteration my tests showed it was slower than the first method. The first method took 625ms and the second 705ms.
You can use LINQ and iterate only one time, with the following code, but at the core you are doing about the same thing. Depending on what else your code needs to do, this may be better than your current approach.
Personally, I would lean towards Selman's example, for readability sake.
double[] max = new double[6];
double xmax = 0.0;
double ymax = 0.0;
double zmax = 0.0;
myLinqObject.ForEach(x =>
{
xmax = (x.bounds[1] > xmax ? x.bounds[1] : xmax);
ymax = (x.bounds[3] > ymax ? x.bounds[3] : ymax);
zmax = (x.bounds[5] > zmax ? x.bounds[5] : zmax);
});
Important Note: Attempting this in code before C# 5.0 may result in wrong values because of a breaking change in the way linq closures worked. More info: http://davefancher.com/2012/11/03/c-5-0-breaking-changes/
You can use Enumerable.Aggregate() with Math.Max() to produce an array of max values:
myObject.Aggregate(new double[]{0,0,0}, (max, o) => new double[] {
Math.Max(max[0], o.Bounds[1]),
Math.Max(max[1], o.Bounds[3]),
Math.Max(max[2], o.Bounds[5])
});
http://rextester.com/KSBAG65974
Edit: I would think this would be the correct approach, as it takes advantage of Linq's ability to iterate the collection just once to get all 3 values. But, in practice, calling Enumerable.Max() 3 times is actually faster: http://rextester.com/QNPL66232
+1 to Enigmativity's answer for identifying that the cause of the slowness with Aggregate() is from garbage collection.
You can use this:
double max = myEnumerable.Max();
double min = myEnumerable.Min();
How do I multiply the contents of a list <double>?
List<double> mult=new List<double>{3, 5, 10};
So far I have:
double r=0.0;
for(int i=0;i<mult.Count;i++)
{
r=mult[i]*mult[(i+1)];
}
To fix your loop, start with 1.0 and multiply each item in the list, like this:
double r = 1.0;
for(int i = 0; i < mult.Count; i++)
{
r = r * mult[i]; // or equivalently r *= mult[i];
}
But for simplicity, you could use a little Linq with the Aggregate extension method:
double r = mult.Aggregate((a, x) => a * x);
What do you mean by multiply? If you like to calculate the product, then your code is wrong and the correct code is
double r=1.0;
for(int i=0;i<mult.Count;i++)
{
r *= mult[i];
}