2012-02-20 2 views
0

мне нужно в среднем 3 IEnumerable коллекции и создать новый IEnumerable с результатом следующим образом:Среднее 3 IEnumerables

var result1 = GetResult1()//Returns an enumerable collection having elements 1,2,3,4 

var result2 = GetResult2()//Returns an enumerable collection having elements 3,4,2,6 

var result3 = GetResult3()//returns an enumerable collection having elements 2,5,1,6 

//I need to create a collection which has the averages of the above results as below: 

var result4 = GetResult4()//Should return 2.00,3.67,2.33,5.33. 
  • Каждый результат будет иметь одинаковое число элементов, т.е. Result1, result2, result3 будет иметь одинаковое количество элементов (в данном случае 4, но на самом деле он может варьироваться до 1500).

  • Каждый элемент в результате соответствует среднему значению результатов, то есть в коллекции result4 первый элемент будет равен 1,3,2, что соответствует среднему значению первого элемента в result1, result2, result3 соответственно и, следовательно, вперед.

  • Полученная коллекция должна быть имеющие знаков после запятой округляется до 2.

Очевидный ответ должен перебирать каждого элемента в коллекции и создавать элементы в результирующей коллекции вручную (т.е. через а, для цикл), однако я хочу избежать этого, поскольку результаты будут иметь около 1500 элементов в каждой коллекции и хотели бы сделать какую-то ленивую оценку с помощью LINQ.

Пожалуйста, помогите мне с некоторыми указателями?

Приветствия, -Mike

ответ

7

Если вы используете .NET 4, вы можете использовать Enumerable.Zip хороший эффект здесь:

var averages = result1.Zip(result2, (x, y) => x + y) 
         .Zip(result3, (xy, z) => (xy + z)/3.0d) 
         .ToList(); 

Это не будет делать какие-либо округление - которые обычно более подходит для форматирование шаг. Обратите внимание, что значения могут заканчиваться только 0, 0,33 или 0,67, так как вы только делитесь на 3. Здесь я использовал double, но другой вариант должен был бы использовать decimal - это зависит от того, что значения действительно означают.

+0

Представьте себе ряд фибоначчи с первыми 1000 номерами серии в каждой коллекции, то есть результат 1, результат2 и результат3, каждый из которых содержит серию. Я считаю, что вы бы использовали десятичное значение для результата4, тогда, правильно? – Mike

+0

@Mike: Я не знаю, если честно. Там нет «единицы», на самом деле ... легче сказать с конкретными суммами, такими как «высота» и «зарплата». Не могли бы вы просто вернуть сумму, а не разделить ее на три? Это одни и те же данные, просто масштабированные ... –

0

Один из способов достижения этого - написать метод, который принимает список списков и выполняет необходимую работу. Что-то вроде:

private static IEnumerable<double> AverageOfLists(params IEnumerable<double>[] values) 
{ 
    var lists = values.Select(v => v.ToList()).ToArray(); 

    for(var i=0;i<lists[0].Count;i++) 
    { 
     var sum = 0.0; 
     for(var j=0;j<lists.Length;j++) 
     { 
      sum+= lists[j][i]; 
     } 
     yield return sum/lists.Length; 
    } 
} 

Использование затем будет

var result4 = AverageOfLists(result1,result2,result3); 

Живой пример: http://rextester.com/IGOSE98291

NB: Не включено округление по той же причине, упомянутой @ Джон; округление - шаг форматирования/отображения.

+0

Не то, чтобы это требовало, чтобы все данные были извлечены в память, когда в этом нет никакой реальной необходимости. Все это можно сделать потоковым способом. –

Смежные вопросы