'Modify List<T> using Linq to Average rows with matching designator

I have a .csv file wherein each row of data represents a part and its associated parameters. e.g. Name, Y-Position, etc. I have defined a class to represent each part and have already parsed the .csv into List<Part> parts

However, the CSV file contains multiple rows with the same Name. I want to reduce List<Part> parts combining rows of same Name and averaging Y-Position.

Input: .csv

Name,XPosition,YPosition
A,10,1
B,10,4
C,10,3
C,10,5
D,12,6
D,12,8

I've created List<Part> parts from this data.

Desired output: List<Parts> part containing:

Part { Name="A", YPosition=1 },
Part { Name="B", YPosition=4 },
Part { Name="C", YPosition=4 },
Part { Name="D", YPosition=7 }

I've tried:

List<Part> parts = parts
.GroupBy(p => p.Name)
.Select(g => new Part()
{
    Name = g.Key, 
    YPosition = g.Average(p => p.YPosition)
}
foreach (Part g in parts)
{
    Console.WriteLine(g.Name + "," + g.XPosition + "," + g.YPosition);
}

But XPosition is not passed to parts...



Solution 1:[1]

It looks like you are not selecting the XPosition when you are getting the other information from the Part. I have added a select statement below to grab the first value of the XPosition from the Part. I ran this snippet of code and was getting the desired XPosition. Hopefully that solves your problem.

List<Part> parts = parts
.GroupBy(p => p.Name)
.Select(g => new Part()
{
    Name = g.Key, 
    XPosition = g.Select(p => p.XPosition).FirstOrDefault(),
    YPosition = g.Average(p => p.YPosition)
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Brook Stang