Reputation: 3284
I need to average 3 IEnumerable collection and create a new IEnumerable with the result as follows:
var result1 = GetResult1()//Returns an enumerable collection having elements 1,2,3,4
var result2 = GetResult2()//Returns an enumerable collection having elements 3,4,2,6
var result3 = GetResult3()//returns an enumerable collection having elements 2,5,1,6
//I need to create a collection which has the averages of the above results as below:
var result4 = GetResult4()//Should return 2.00,3.67,2.33,5.33.
Each results will be having the same number of elements i.e result1, result2, result3 will be having the same number of elements (in this case 4, but actually it can range till 1500).
Each element in the result corresponds to the average value of the results i.e in result4 collection the first element will be an average of 1,3,2 which corresponds to the average of the first element in result1,result2,result3 respectively and hence forth.
The resultant collection should be having decimal places rounded to 2.
An obvious answer is to iterate through each element in the collections and create the elements in the resultant collection manually (i.e via a for loop), however I want to avoid it as the results will have close to 1500 elements in each collection and would like to do some sort of lazy evaluation using LINQ.
Please can you help me with some pointers?
Cheers, -Mike
Upvotes: 0
Views: 114
Reputation: 136134
One way to achieve this is to write a method which takes a list of lists, and does the necessary work. Something like:
private static IEnumerable<double> AverageOfLists(params IEnumerable<double>[] values)
{
var lists = values.Select(v => v.ToList()).ToArray();
for(var i=0;i<lists[0].Count;i++)
{
var sum = 0.0;
for(var j=0;j<lists.Length;j++)
{
sum+= lists[j][i];
}
yield return sum/lists.Length;
}
}
Usage would then be
var result4 = AverageOfLists(result1,result2,result3);
Live example: http://rextester.com/IGOSE98291
NB: Not included rounding for the same reason @Jon mentioned; rounding is a formatting/display step.
Upvotes: 0
Reputation: 1502016
If you're using .NET 4, you can use Enumerable.Zip
to good effect here:
var averages = result1.Zip(result2, (x, y) => x + y)
.Zip(result3, (xy, z) => (xy + z) / 3.0d)
.ToList();
This won't do any rounding - that would normally be more appropriate for a formatting step. Note that the values can only end with 0, 0.33, or 0.67 anyway, as you're only dividing by 3. Here I've used double
but another option would be to use decimal
- it depends on what the values really mean.
Upvotes: 7