Elegant averaging of arrays from different instances of an object in C #

I have a list of objects of the same type, each of which has a property, which is an array of floats. Taking this list as input, what is the easiest way to return a new array, which is the average number of arrays in the list?

Input objects are as follows:

Class MyDatas
{
    float [] DataValues;
}

...

List<MyDatas> InputList;
float [] result;

Arrays of DataValues ​​will have the same length. Each element of the result array will be the average of the corresponding elements in the array of each member of the list. For instance:result[0] = (InputList[0].DataValues[0] + InputList[1].DataValues[0] + ... ) / InputList.Count

Of course, I could overdo this with foreach inside the for loop, and then for the for loop after that, but it seems to me that this should be done with one or two LINQ lines. Any tips?

+5
3
float[] result = inputList.Select(c => c.DataValues)
                          .Transpose()
                          .Select(r => r.Average())
                          .ToArray();

Transpose .

+5

Pure LINQ:

var result = InputList
    .SelectMany(x => x.DataValues.Select((y, i) => new { y, i }))
    .GroupBy(a => a.i, b => b.y, (k, v) => v.Average());

:

List<MyDatas> InputList = new List<MyDatas>();
InputList.Add(new MyDatas { DataValues = new float[] { 1, 2, 3 } });
InputList.Add(new MyDatas { DataValues = new float[] { 4, 5, 6 } });
InputList.Add(new MyDatas { DataValues = new float[] { 7, 8, 9 } });

var result = InputList
    .SelectMany(x => x.DataValues.Select((y, i) => new { y, i }))
    .GroupBy(a => a.i, b => b.y, (k, v) => v.Average());


foreach (var item in result)
{
    Console.WriteLine(item);
}

:

4
5
6
+3

How about this?

var averages = (from index in Enumerable.Range(0, InputList[0].DataValues.Length)
                select (from item in InputList
                        select item.DataValues[index]).Average()).ToArray();

Or using the free syntax:

var averages = Enumerable.Range(0, InputList[0].DataValues.Length)
               .Select(index => InputList.Average(item => item.DataValues[index]))
               .ToArray();

This clearly shows that what you are really doing is calculating the result for each index in the DataValues ​​arrays.

+2
source

All Articles