Search code examples
vb.netlinqlinq-group

Linq Group by Sum Lists Elementwise


The list of doubles SC is of same size for all of CTable. I would like add SC grouped by CTable.Ch. The result should be a List of sums. Is there an operator/customization for that?

Public Class SCRow
 Public L As String
 Public Ch As String
 Public SC As List(Of Double)
End Class

Dim CTable AS New List(Of SCRow)

Dim AggrC =
    From C In CTable
    Group C By Key = C.Ch
    Into Group
    Select New With
    {
       .Ch= Key,
       .SumSC = Group.Sum(Function(x)  ???)
    }

Example:

CTable.Add(New SCRow With {.L = "L1", .Ch = "Ch1", .SC = New List(Of Double)(New Double() {1.0, 2.0})})
CTable.Add(New SCRow With {.L = "L1", .Ch = "Ch2", .SC = New List(Of Double)(New Double() {3.0, 4.0})})
CTable.Add(New SCRow With {.L = "L2", .Ch = "Ch1", .SC = New List(Of Double)(New Double() {5.0, 6.0})})


Output:
Ch1 {6=1+5, 8=2+6}
Ch2 {3, 4}

Solution

  • It can be done using Aggregate extension method along with Zip method. I have written the code in C#. Please translate it to VB.Net. Hope it will help.

    Aggregate: Performs a specified operation to each element in a collection, while carrying the result forward.

    Zip: The Zip extension method acts upon two collections. It processes each element in two series together.

    public class SCRow
    {
        public string L { get; set; }
        public string CH { get; set; }
        public List<double> SC { get; set; }
    }
    class Program
    {
    
        static void Main(string[] args)
        {
            var CTable = new List<SCRow>{
                new SCRow { L = "L1",  CH = "Ch1", SC = new List<double> { 1.0, 2.0}},
                new SCRow { L = "L1",  CH = "Ch2", SC = new List<double> { 3.0, 4.0}},
                new SCRow { L = "L2",  CH = "Ch1", SC = new List<double> { 5.0, 6.0}},
            };
    
            var result = CTable.GroupBy(c => c.CH)
                .Select(x => new
                {
                    Value = x.Aggregate((curr, next) => new SCRow
                    {
                        CH = x.Key,
                        SC = curr.SC.Zip(next.SC, (n1, n2) => n1 + n2).ToList()
                    })
                })
                .Select(y => new {
                  CH = y.Value.CH,
                  ScSum = y.Value.SC
                }).ToList();
    
        }
    }