Este enfoque:
1) Grupos por Fecha
2) para cada fecha, los grupos de rango y calcula el total
3) para cada fecha, se selecciona el elemento con el mayor total
4) Se termina con el resultado de su
public sealed class Program
{
public static void Main(string[] args)
{
var items = new[]
{
new { ID = 1, Date = new DateTime(10, 10, 10), Range = "9-10" },
new { ID = 2, Date = new DateTime(10, 10, 10), Range = "9-10" },
new { ID = 3, Date = new DateTime(10, 10, 10), Range = "9-10" },
new { ID = 4, Date = new DateTime(10, 10, 10), Range = "8-9" },
new { ID = 5, Date = new DateTime(10, 10, 11), Range = "1-2" },
new { ID = 6, Date = new DateTime(10, 10, 11), Range = "1-2" },
new { ID = 7, Date = new DateTime(10, 10, 12), Range = "5-6" },
};
var itemsWithTotals = items
.GroupBy(item => item.Date) // Group by Date.
.Select(groupByDate => groupByDate
.GroupBy(item => item.Range) // Group by Range.
.Select(groupByRange => new
{
Date = groupByDate.Key,
Range = groupByRange.Key,
Total = groupByRange.Count()
}) // Got the totals for each grouping.
.MaxElement(item => item.Total)); // For each Date, grab the item (grouped by Range) with the greatest Total.
foreach (var item in itemsWithTotals)
Console.WriteLine("{0} {1} {2}", item.Date.ToShortDateString(), item.Range, item.Total);
Console.Read();
}
}
/// <summary>
/// From the book LINQ in Action, Listing 5.35.
/// </summary>
static class ExtensionMethods
{
public static TElement MaxElement<TElement, TData>(this IEnumerable<TElement> source, Func<TElement, TData> selector) where TData : IComparable<TData>
{
if (source == null)
throw new ArgumentNullException("source");
if (selector == null)
throw new ArgumentNullException("selector");
bool firstElement = true;
TElement result = default(TElement);
TData maxValue = default(TData);
foreach (TElement element in source)
{
var candidate = selector(element);
if (firstElement || (candidate.CompareTo(maxValue) > 0))
{
firstElement = false;
maxValue = candidate;
result = element;
}
}
return result;
}
}
De acuerdo con LINQ en acción (Capítulo 5.3.3 - ¿LINQ to Objects perjudicará el rendimiento de mi código?), usar el método de extensión MaxElement es uno de los enfoques más eficaces. Creo que el rendimiento sería O (4n); uno para el primer GroupBy, dos para el segundo GroupBy, tres para el Count() y cuatro para el bucle dentro de MaxElement.
El enfoque de DrDro va a ser más como O (n^2) ya que bucles toda la lista para cada elemento de la lista.
El enfoque de StriplingWarrior va a estar más cerca de O (n log n) porque ordena los elementos. Aunque lo admitiré, puede haber alguna magia loca que no entiendo.
¿Puede explicar qué es lo que debe hacer? Como Max devuelve un solo valor, no estoy seguro de cómo puede ayudar en esta cuestión. – Jla