Search code examples
c#.netlinqlistrecord

How to add two records with LINQ?


I need help on a problem I have. I have a list with several fields including contract, installment and amount.

I need to create a new list based on these fields, including all the others, of course.

So, for every contract with two installments, I need to sum the amounts into the first installment, while maintaining the second one.

You have an example below.

Is this possible?

...contract    instalment    amount ...
...1           1             100    ... 
...1           2             1000   ...
...2           1             100    ...
...3           1             1000   ...
...4           1             200    ...
...4           2             100    ...
...5           1             1000   ...

...contract    instalment    amount ...
...1           1             1100   ... 
...1           2             1000   ...
...2           1             100    ...
...3           1             1000   ...
...4           1             300    ...
...4           2             100    ...
...5           1             1000   ...

Solution

  • I think you want:

    var result = from record in records
                 group record by record.Contract into contractGroup
                 let orderedGroup = contractGroup.OrderBy(r => r.Instalment).ToList()
                 let aggregatedItem = new Record 
                                      {
                                          Contract = contractGroup.Key,
                                          Instalment = orderedGroup.First().Instalment,
                                          Amount = orderedGroup.Sum(r => r.Amount) 
                                      }
                 from resultRecord in new[] { aggregatedItem }
                                            .Concat(orderedGroup.Skip(1))              
                 select resultRecord;
    

    Note that in your sample, you only handle cases where groups contain one or two items, but the above code will also work for three or more items in a group by aggregating the first item from all the others.

    EDIT:

    Since you want to mutate the first record in each group rather than create a new one, I would do:

    foreach(var contractGroup in records.GroupBy(record => record.Contract))
    {
         // Use Aggregate or a dedicated MinBy operator
         // if you don't want the sorting overhead.
         var aggregateItem = contractGroup.OrderBy(record => record.Instalment)
                                          .First();     
    
         aggregateItem.Amount = contractGroup.Sum(record => record.Amount);  
    }
    
    // Now use 'records' as before as the subsequent data-source.