Dieser Ansatz:
1) Gruppen nach Datum
2) Gruppiert für jedes Datum nach Bereich und berechnet die Summe
3) Wählt für jedes Datum die Position mit der höchsten Gesamtsumme aus.
4) Sie haben Ihr Ergebnis erhalten
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;
}
}
Laut LINQ in Action (Kapitel 5.3.3 - Will LINQ to Objects hurt the performance of my code?) ist die Verwendung der MaxElement-Erweiterungsmethode einer der effizientesten Ansätze. Ich denke, die Leistung wäre O(4n); eine für die erste GroupBy, zwei für die zweite GroupBy, drei für die Count() und vier für die Schleife innerhalb von MaxElement.
DrDro's Ansatz wird mehr wie O(n^2) sein, da es die gesamte Liste für jedes Element in der Liste schleift.
Der Ansatz von StriplingWarrior liegt näher an O(n log n), da er die Elemente sortiert. Aber ich gebe zu, dass da vielleicht ein bisschen verrückte Magie drinsteckt, die ich nicht verstehe.