Я считаю, что это должно опережать GroupBy
предложение (см краткое описание ниже):
IEnumerable<Event> DistinctEvents(IEnumerable<Event> events)
{
var dict = new Dictionary<int, Event>();
foreach (Event e in events)
{
Event existing;
if (!dict.TryGetValue(e.Id, out existing) || e.ExpirationTime < existing.ExpirationTime)
{
dict[e.Id] = e;
}
}
foreach (Event e in dict.Values)
{
yield return e;
}
}
Объяснение: Хотя это и the GroupBy
method proposed by Ani имеют одинаковую алгоритмической сложности (насколько я может сказать, во всяком случае), вышеупомянутый подход более эффективен на практике по двум причинам.
GroupBy
внутренне использует Lookup<TKey, TValue>
(очень похож на Dictionary<TKey, List<TValue>>
), который фактически заполняет внутренние коллекции с содержимым входной последовательности. Это требует большей памяти, а также имеет влияние на производительность, в частности, из-за того, что в то время, когда подкатегории будут иметь , амортизируются O (1) время вставки, они будут иногда нуждаться в изменении размера, что будет O (N) (где N - размер подсекции). Это не большое дело, но все еще намного больше работы, которую вы действительно делаете. нужен.
- Следствием точки # 1 является то, что это, в свою очередь, требует перебора каждого элемента в последовательности ввода до
GroupBy
может обеспечить перечислитель (так что это отложено исполнение, но потом весь входной последовательности должна быть итеративно до того итерации по результату GroupBy
). Затем вы повторяете по каждой группе снова в звонок Aggregate
; так что во всех случаях вы повторяете элементы во входной последовательности дважды, что больше времени, чем необходимо для выполнения поставленной задачи.
Как я уже сказал, алгоритмическая сложность одинакова, что означает, что два подхода должны быть одинаково масштабируемыми; это просто быстрее. Я взял на себя смелость тестировать оба подхода (из-за любопытства, в основном), и нашел выше, чтобы выполнить примерно в половине случаев и вызвать меньше коллекций GC (приблизительное приближение использования памяти), чем подход GroupBy
.
Это минутные проблемы, которые обычно представляют собой пустую трату времени, чтобы слишком много думать. Единственная причина, по которой я упоминаю их, заключается в том, что вы попросили эффективное решение (и даже выделено жирным шрифтом); поэтому я решил, что вы захотите принять во внимание эти факторы.
'оставьте событие с наименьшим значением ExpirationTime?' Что вы имеете в виду? –
Он имеет в виду держать ((французский adibe?) – Guillaume86