2016-04-26 9 views
1

Я пытаюсь вычислить скользящие средние из каждых четырех значений в списке массивов и добавить эти значения в отдельный список массивов. Мой первоначальный список массива называется numlist и содержит значение от 1 до 9Как рассчитать скользящее среднее списка массивов C#?

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

numlist.Add(1); 
numlist.Add(2); 
numlist.Add(3); 
numlist.Add(4); 
numlist.Add(5); 
numlist.Add(6); 
numlist.Add(7); 
numlist.Add(8); 
numlist.Add(9); 

Когда он вычисляет средние качению, он должен сделать это в пути, как это:

первых средний = (1 + 2 + 3 + 4)/4

второй средний = (2 + 3 + 4 + 5)/4

третий средний = (3 + 4 + 5 + 6)/4

и так далее

поэтому второй список массива,

List<double> avelist = new List<double>(); 

должна содержать следующие значения

{2.5, 3.5, 4.5, 5.5, 6.5, 7.5} 

Как я могу добиться этого?

+0

Что вы уже пробовали? – yaakov

ответ

1

Вы можете использовать LINQ, как это:

List<double> averages = Enumerable.Range(0, numlist.Count - 3). 
           Select(i => numlist.Skip(i).Take(4).Average()). 
           ToList(); 

В вашем примере, это идет от i = 0 к i = 5 и занимает 4 элемента из списка, начиная с индекса i и вычисляет их среднее значение.

Вы можете вывести результат так:

Console.WriteLine(string.Join(" ", averages)); 

Метод с переменной "шириной" для скользящей средней может выглядеть следующим образом:

public List<double> RollingAverage(List<int> source, int width) 
{ 
    return Enumerable.Range(0, 1 + numlist.Count - width). 
           Select(i => numlist.Skip(i).Take(width).Average()). 
           ToList(); 
} 

Документация:

+0

Я пробовал это, но когда я пытаюсь распечатать его на консоли с помощью Console.WriteLine (в среднем); он только распечатывает: System.Collections.Generic.List'1 [System.Double] – coder

+0

@coder, конечно, потому что 'Console.WriteLine' вызывает' ToString() 'в' List ', который выводит тип. Обновлен мой ответ с правильным способом вывода. –

+0

Что делает numlist.Count-3 do – coder

1

Следующий код поможет вам:

List<int> numlist = Enumerable.Range(1, 10).ToList();// generating list 
List<double> avelist = new List<double>(); 
Dictionary<int, double> rollingAvg = new Dictionary<int, double>(); 
int limit = 4, i = 0; 
while (limit + i <= numlist.Count) 
{ 
    avelist.Add(numlist.Skip(i).Take(limit).Average()); 
    i++; 
} 

avelist будет иметь следующий вид @ конца выполнение :

{2.5, 3.5, 4.5, 5.5, 6.5, 7.5} 
+0

значения, которые находятся в avelist: 2.5, 3.5 и т. Д. - это результат, который я пытаюсь получить из первого списка массивов. Так что бы это не нашло скользящих средних средних значений – coder

+0

@coder: Приятно, не могли бы вы посмотреть обновления –

1

Если вы заботитесь о производительности, вы можете использовать очереди и обрабатывать каждый элемент в источнике только один раз:

IEnumerable<double> RollingAverages(IEnumerable<int> numbers, int length) { 
    var queue = new Queue<int>(length); 
    double sum = 0; 
    foreach (int i in numbers) { 
     if (queue.Count == length) { 
      yield return sum/length; 
      sum -= queue.Dequeue(); 
     } 
     sum += i; 
     queue.Enqueue(i); 
    } 
    yield return sum/length; 
} 

Вызов:

foreach (double a in RollingAverages(new List<int> {1,2,3,4,5,6,7,8,9}, 4)) { 
    Console.WriteLine(a); 
}