Are you looking for a moving average? Having a window of size == 3
you compute averages of 0..2
items, then of 1..3
items, etc:
(1, 'A', 100), -> not enough data to compute moving average
(2, 'X', 200), -> not enough data to compute moving average
(3, 'D', 300), -> (100 + 200 + 300) / 3 == 200
(5, 'B', 300), -> (200 + 300 + 300) / 3 == 267
(6, 'Z', 300), -> (300 + 300 + 300) / 3 == 300
(7, 'G', 300), -> (300 + 300 + 300) / 3 == 300
If it's your task, then you can do it as follow:
private static IEnumerable<(T item, double average)> MovingAverage<T>(
IEnumerable<T> source, Func<T, double> selector, int windowSize) {
if (source is null)
throw new ArgumentNullException(nameof(source));
if (selector is null)
throw new ArgumentNullException(nameof(selector));
if (selector is null)
throw new ArgumentNullException(nameof(selector));
if (windowSize <= 0)
throw new ArgumentOutOfRangeException(nameof(windowSize));
double total = 0.0;
var priors = new Queue<double>();
foreach (var item in source) {
double value = selector(item);
priors.Enqueue(value);
total += value;
while (priors.Count > windowSize)
total -= priors.Dequeue();
if (priors.Count == windowSize)
yield return (item, total / windowSize);
}
}
Demo:
var data = new (int id, char name, int value)[] {
(1, 'A', 100),
(2, 'X', 200),
(3, 'D', 300),
(5, 'B', 300),
(6, 'Z', 300),
(7, 'G', 300),
};
var result = string.Join(Environment.NewLine,
MovingAverage(data, item => item.value, 3)
.Select(item => $"{item.item} :: {Math.Round(item.average)}"));
Console.Write(result);
Output:
(3, D, 300) :: 200 // (100 + 200 + 300) / 3
(5, B, 300) :: 267 // (200 + 300 + 300) / 3
(6, Z, 300) :: 300 // (300 + 300 + 300) / 3
(7, G, 300) :: 300 // (300 + 300 + 300) / 3
Having moving average computed, you can easily obtain max record from it with a help of Linq:
using System.Linq;
...
var max = MovingAverage(data, item => item.value, 3)
.MaxBy(pair => pair.average);
Console.WriteLine($"Max: {max.item} :: {max.average}");
Output:
Max: (6, Z, 300) :: 300
which means that max moving average (that is 300
) group starts from (6, Z, 300)
item.
Fiddle