Reputation: 9
What I'm trying to do is get the Time
where Math.Abs(A + B + C)
is closest to 0 for each ID
. It's quite hefty. I have a list (that I got from a CSV file) that kind of looks like this:
|------------|------------|-------|-------|-------|
| Time | ID | A | B | C |
|------------|------------|-------|-------|-------|
| 100 | 1 | 1 | 2 | 2 |
|------------|------------|-------|-------|-------|
| 100 | 2 | 3 | 4 | 3 |
|------------|------------|-------|-------|-------|
| 200 | 1 | 1 | 0 | 3 |
|------------|------------|-------|-------|-------|
| 200 | 2 | 1 | 2 | 0 |
|------------|------------|-------|-------|-------|
I have the following code, and while it it not complete yet, it technically prints the value that I want. However when I debug it, it doesn't seem to be looping through the IDs, but does it all in one loop. My idea was that I could get all the distinct ID
s, then go through the distinct Time
for each, put them all in a temporary list, then just use Aggregate
to get the value closest to 0. But I feel there should be a more efficient approach than this. Is there a quicker LINQ function I can use to achieve what I want?
for (int i = 0; i < ExcelRecords.Select(x => x.Id).Distinct().Count(); i++)
{
for (int j = 0; j < ExcelRecords.Select(y => y.Time).Distinct().Count(); j++)
{
List<double> test = new List<double>();
var a = ExcelRecords[j].a;
var b = ExcelRecords[j].b;
var c = ExcelRecords[j].c;
test.Add(Math.Abs(pitch + yaw + roll));
Console.WriteLine(Math.Abs(pitch + yaw + roll));
}
}
Upvotes: 0
Views: 438
Reputation: 20353
I think the most readable way would be to group by Id
, order each group and select the first Time
from each:
var times = ExcelRecords.GroupBy(x => x.Id)
.Select(grp => grp.OrderBy(item => Math.Abs(item.A + item.B + item.C)))
.Select(grp => grp.First().Time);
Upvotes: 0
Reputation: 24641
Using explicit for loops like this is throwing the power and flexibility of LINQ out the window. LINQ's power comes from enumerators which can be used on their own or in conjunction with a foreach
loop.
You are also doing way more work than necessary using Distinct
to first get a list and then using that list to selectively group the rows into batches. This is what GroupBy
was designed for.
var times = ExcelRecords.GroupBy((row) => row.Id)
.Select((g) => g.Aggregate((min, row) => Math.Abs(row.a + row.b + row.c) < Math.Abs(min.a + min.b + min.c) ? row : min).Time)
.ToList();
Upvotes: 2