I have a list of objects which have 2 string attributes and a few double attributes each – there are duplicate rows in the sense that the string attributes are the same, while the double attributes are different. I’m trying to merge these duplicates into a single new row that is computed from the values of the double attributes. Simplified example:
1. A, Text1, 5
2. A, Text2, 4
3. B, Text1, 7
4. A, Text1, 3
Taking the ‘computed row’ as a simple average, I should end up with:
1. A, Text1, 4 (5+3)/2
2. A, Text2, 4
3. B, Text1, 7
This is what I’m doing at the moment:
var groups = (from t in MyList group t by new { t.Field1, t.Field2});
foreach (var @group in groups)
{
if (@group.Count() > 1)
{
var newRow = new MyObject
{
Field1 = @group.ElementAt(0).Field1,
Field2 = @group.ElementAt(0).Field2,
Field3 = @group.Average(i => i.Field3)
};
}
}
Which works fine. I’m just not sure how to replace the rows in the groups I’m iterating over, as there are no remove methods available for the groups. I had originally tried to do this with a coupe of nested for loop comparisons, but since I couldn’t modify the list I was iterating over I stored matching indexes, but that meant that I had n*(n-1)/2 matches…
Am I missing a perfectly simple way to do this? I can’t believe it’s very difficult, but I haven’t been able to work it out yet.
Answering my own question rather than deleting it as it might be of use to someone who had a similar brainblock:
I was overcomplicating things – I have ended up just creating and returning a new list with the new rows + the rows that did not need processing.
Simples.
Note this does do the processing on all groups, even those with only 1 item. Although they don’t need to be processed, the average of one value is obviously that value, and it avoids the extra
if(...) {process and add} else {add}. I doubt the overhead will be noticeable but it’s something to keep an eye on.