I suggest to remove the two times execution of ElementAt
, that makes your code faster.
List<(int length, int count)> result = new();
int column = 0;
while (column < averages[0].Count) // averages is list of lists
{
(int length, int count) cumulative = (0, 0);
for (int i = 0; i < averages.Count; i++)
{
var elm = averages[i].ElementAt(column);
cumulative.length += elm.length;
cumulative.count += elm.count;
}
result.Add(cumulative);
column++;
}
It will be more readable and maintainable code if you use LINQ
List<(int item1, int item2)> averages1 = new List<(int item1, int item2)>();//10 elements
List<List<(int length, int count)>> averages = new();
List<Tuple<int, int>> result = averages
.Select(x =>
new Tuple<int, int>(
x.Select(y => y.length).Sum(),
x.Select(y => y.count).Sum())
).ToList();
Someone may think it be much more faster if you use parallel programming
ConcurrentBag<Tuple<int, int>> result= new ConcurrentBag<Tuple<int, int>>();
averages
.AsParallel()
.ForAll(x => result.Add(
new Tuple<int, int>(
x.Select(y => y.length).Sum(),
x.Select(y => y.count).Sum())
));
Testing with large dataset it seems OP's code is faster

using System;
using System.Text;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.ComponentModel.DataAnnotations;
using System.Runtime.CompilerServices;
using System.Collections.Concurrent;
List<List<(int length, int count)>> averages = new();
for (int i = 0; i < 100000; i++)
{
var list = new List<(int, int)> { (0, 0), (1, 10), (2, 20), (3, 30), (4, 40) };
averages.Add(list);
}
var stage = DateTime.Now;
//OP's code
List<(int length, int count)> result = new();
int column = 0;
while (column < averages[0].Count) // averages is list of lists
{
(int length, int count) cumulative = (0, 0);
for (int i = 0; i < averages.Count; i++)
{
var elm = averages[i].ElementAt(column);
cumulative.length += elm.length;
cumulative.count += elm.count;
}
result.Add(cumulative);
column++;
}
Console.WriteLine("OP's code: " + (DateTime.Now - stage).TotalMilliseconds);
stage = DateTime.Now;
//LINQ rewrite
List<Tuple<int, int>> result2 = averages
.Select(x =>
new Tuple<int, int>(
x.Select(y => y.length).Sum(),
x.Select(y => y.count).Sum())
).ToList();
Console.WriteLine("LINQ rewrite: " + (DateTime.Now - stage).TotalMilliseconds);
stage = DateTime.Now;
//LINQ+PP
ConcurrentBag<Tuple<int, int>> result1 = new ConcurrentBag<Tuple<int, int>>();
averages
.AsParallel()
.ForAll(x => result1.Add(
new Tuple<int, int>(
x.Select(y => y.length).Sum(),
x.Select(y => y.count).Sum())
));
Console.WriteLine("LINQ & PP: " + (DateTime.Now - stage).TotalMilliseconds);
stage = DateTime.Now;