Более интересным будет вопрос, как сделать это на сервере, например, чтобы следующий запрос был преобразован в LINQ to SQL.
var q = from single in Enumerable.Range(1, 1)
let xs = sourceSequence
select new
{
Aggregate1 = xs.Sum(),
Aggregate2 = xs.Average(),
// etc
};
Но нет смысла пытаться его втиснуть в один запрос, если вы используете LINQ to Objects. Просто напишите агрегаты отдельно:
var aggregate1 = xs.Sum();
var aggregate2 = xs.Average();
// etc
Другими словами:
var xs = from a in listOfAs
from b in a.Bs
select new { A=a, B=b };
var average1 = xs.Average(x => (x.B.Completed - x.A.Created).TotalSeconds);
var average2 = xs.Average(x => (x.B.Completed - x.B.Created).TotalSeconds);
Правильно ли я понял?
Редактировать: Дэвид Б. ответил аналогичным образом. Я забыл преобразовать TimeSpan в простой числовой тип, поддерживаемый методом Average. Используйте TotalMilliseconds / Seconds / Minutes или любой другой подходящий масштаб.
Sql и Linq различаются по некоторым пунктам. Sql имеет неявную группировку - возьмите все это и сделайте одну группу. В linq можно имитировать неявную группировку, введя константу для группировки.
var query =
from i in Enumerable.Repeat(0, 1)
from a in AList
from b in a.BList
select new {i, a, b} into x
group x by x.i into g
select new
{
Avg1 = g.Average(x => (x.b.CompletedDate - x.a.CreatedDate)
.TotalMilliseconds ),
Avg2 = g.Average(x => (x.b.CompletedDate - x.b.CreatedDate)
.TotalMilliseconds )
};
Давайте начнем с получения среднего времени между началом B и finish:
1) Сначала вам нужна разница во времени между началом и концом каждого объекта B, чтобы вы сделали это:
List<TimeSpan> timeSpans = new List<TimeSpan>();
foreach (B myB in BList)
{
TimeSpan myTimeSpan = myB.CompletedDate.Subtract(myB.CreatedDate);
timeSpans.Add(myTimeSpan);
}
2) Теперь вам нужно получить среднее значение этого. Вы можете сделать это с помощью лямбда-выражений:
//This will give you the average time it took to complete a task in minutes
Double averageTimeOfB = timeSpans.average(timeSpan => timeSpan.TotalMinutes);
Теперь вы можете сделать то же самое, чтобы получить среднее время между началом A и концом B следующим образом:
1) Получите разницу во времени для даты начала A и каждого из B дата завершения:
List<TimeSpan> timeSpans_2 = new List<TimeSpan>();
foreach (B myB in BList)
{
TimeSpan myTimeSpan = myB.CompletedDate.Subtract(objectA.CreatedDate);
timeSpans_2.Add(myTimeSpan);
}
2) Получите среднее значение этих временных различий точно так же, как указано выше:
//This will give you the average time it took to complete a task in minutes
Double averageTimeOfAandB = timeSpans_2.average(timeSpan => timeSpan.TotalMinutes);
И готово. Я надеюсь, что это помогает. Обратите внимание, что этот код не был протестирован.
РЕДАКТИРОВАТЬ: Помните, что LINQ использует выражения Lamda, но представляет собой скорее синтаксический сахар (мало что знаю о реализации, поэтому я надеюсь, что вы не будете обвинять меня). А также вы можете заключить предоставляемые мной реализации в методы, чтобы вы могли вызывать их несколько раз для списка объектов A.