Найдите среднее значение коллекции TimeSpans

У меня есть коллекция TimeSpans, они представляют время, потраченное на выполнение задачи. Теперь я хотел бы найти среднее время, затрачиваемое на эту задачу. Это должно быть легко, но по какой-то причине я не получаю правильное среднее значение.

Вот мой код:

private TimeSpan? GetTimeSpanAverage(List<TimeSpan> sourceList)
{
    TimeSpan total = default(TimeSpan);

    var sortedDates = sourceList.OrderBy(x => x);

    foreach (var dateTime in sortedDates)
    {
        total += dateTime;
    }
    return TimeSpan.FromMilliseconds(total.TotalMilliseconds/sortedDates.Count());
}

person hs2d    schedule 13.01.2012    source источник
comment
Пожалуйста, предоставьте примерные данные и какой результат вы получаете и какой результат вы ожидаете. Кстати: заказ не нужен.   -  person Daniel Hilgarth    schedule 13.01.2012


Ответы (3)


Вы можете использовать среднюю перегрузку, которая занимает коллекция длинных параметров:

double doubleAverageTicks = sourceList.Average(timeSpan => timeSpan.Ticks);
long longAverageTicks = Convert.ToInt64(doubleAverageTicks);

return new TimeSpan(longAverageTicks);
person vc 74    schedule 13.01.2012
comment
Это дает мне ошибку: невозможно преобразовать из «двойного» в «длинный» - person hs2d; 13.01.2012
comment
Вместо Ticks вы также можете использовать TotalSeconds, а затем использовать TimeSpan.FromSeconds - person V4Vendetta; 13.01.2012
comment
@ V4Vendetta Да, вы можете, но вы потеряете компоненты менее секунды, которые могут быть полезны, если вы рассчитываете короткие действия. - person vc 74; 13.01.2012
comment
@ vc74 Что ж, в этом случае у вас может быть TotalMilliseconds, также в вашем случае вы используете двойное значение для длинного, поэтому потеря происходит и в этом случае :) - person V4Vendetta; 13.01.2012
comment
@ V4Vendetta Да, но только после того, как будет рассчитано среднее значение, что лучше, чем для каждого промежутка времени. - person vc 74; 13.01.2012

var average = new TimeSpan(sourceList.Select(ts => ts.Ticks).Average());

Обратите внимание, что ваш метод возвращает Nullable, но это не обязательно, если вы не хотите возвращать значение null, если исходный список пуст, и в этом случае сначала выполните отдельную проверку.

person George Duckett    schedule 13.01.2012
comment
Нет перегрузки Enumerable.Average(), которая возвращает значение long, а также нет конструктора TimeSpan, который принимает double в качестве аргумента, поэтому пример мне не подходит. Чтобы компилировать, мне пришлось добавить явное приведение (long) аргумента: var average = new TimeSpan((long)sourceList.Select(ts => ts.Ticks).Average()); - person Konard; 20.08.2019

В дополнение к приведенному выше ответу я бы посоветовал вам взять среднее значение на уровне секунд или миллисекунд (в зависимости от того, что вам нужно)

sourceList.Average(timeSpan => timeSpan.ToTalMilliseconds)

Теперь, используя это значение, вы можете получить новый TimeSpan, используя

TimeSpan avg = TimeSpan.FromMilliseconds(double value here)
person V4Vendetta    schedule 13.01.2012
comment
Я просто хочу предупредить всех, что если ваше среднее значение меньше даже одной миллисекунды, то из-за некоторых проблем с точностью ваше новое среднее значение TimeSpan всегда будет 0. - person Artholl; 29.10.2015
comment
@Artholl Это была моя точная проблема - person Coops; 18.11.2016