Tienus McVinger
Tienus McVinger

Reputation: 477

get "running average" of a list

Say I've got a list:

List<int> numbers = new List<int>();

and I'm trying to get the "running averages" of it. (Sorry, I don't really know how to call it).

For instance:

The first item in this list is 5, the average of 5 is 5, so the first average is 5.

The second item in this list is 7, the average of 5 and 7 is 6, so the second average is 6.

The third item in this list is 10, the average of 5, 7 and 10 is 7.3, so the third average is 7.3 And so on.

Those first average, second average etc are the averages I'm trying to get. How would I go about doing this? I've been searching the internet but honestly I'm not quite sure what I should be looking for. :(

Upvotes: 2

Views: 1703

Answers (4)

Bart Vanseer
Bart Vanseer

Reputation: 548

You need the "Running Average", not the average from the start over all items I assume?

The running average needs a number to tell how far back to look and one to tell how far forward to look.

This will give you the running average:

public List<double> GetRunningAverage(List<double> SourceList, int ItemsBefore, int ItemsAfter)
{
    List<double> TargetList = new List<double>() { };

    // Only makes sense if the list is > 1 of course
    if (SourceList.Count > 1)
    {
        for (int i = 0; i < SourceList.Count; i++)
        {
            int LookBack =
                (ItemsBefore > i ? i : ItemsBefore);
            int LookForward =
                (ItemsAfter < SourceList.Count - i
                ? ItemsAfter : SourceList.Count - i);

            TargetList.Add(SourceList.GetRange(i - LookBack, LookBack + LookForward).Average());
        }
    }
    else
    {
        TargetList.AddRange(SourceList);
    }

    return TargetList;
}

You can then use it like this:

    List<double> FullList = GetRunningAverage(
    new List<double>() { 100, 5, 5, 6, 23, 10, 56, 32, 54, 1, 3, 85, 65, 49, 22, 65, 32, 5, 2, 4, 5, 89, 110, 55, 6, 56, 57 },
    3,  // Looking back 3 items
    3); // Looking forward 3 items

Upvotes: 0

The lists

    List<int> numbers = new List<int>();
    List<double> averages = new List<double>();

test data

    numbers.AddRange(new int[]{5, 7, 10});

    // get average of current List
    averages.Add(numbers.Average());

Such a list of averages all by itself usually doesnt mean much without some other data like number of elements, duration of time or something to qualify it.

This method is better suited when the moving average is not one for one with the values. For instance, the app stores values. Then periodically, say once a minute, the average is calculated and stored.

Upvotes: 2

niceman
niceman

Reputation: 2673

try this:

 string st = Console.ReadLine();
 string[] strs = st.Split(' ');
 List<int> numbers = new List<int>();
 List<double> averages = new List<double>();
 for (int i = 0; i < strs.Length; i++)
 {
     numbers.Add(int.Parse(strs[i]));
     averages.Add(numbers.Average());
 }

this will read the numbers from the standard input, the numbers are separated by space in input.

Upvotes: 5

Selman Gen&#231;
Selman Gen&#231;

Reputation: 101691

You can try something like this:

var averages = Enumerable.Range(1, numbers.Count)
               .Select(x => numbers.Take(x).Average())
               .ToList();

This will generate a sequence from 1 to numbers.Count. Then using Take it will get X element at each time (you can think X as an index, only difference is it starts from 1 and increases one by one up to the numbers.Count) starting from the first element then get their average.Put them into a list.

Upvotes: 4

Related Questions