如何使用LINQ获取Count()的Max()

时间:2010-11-16 23:32:34

标签: linq

我是LINQ的新手,我有这种情况。我有这张桌子:

ID Date  Range
1 10/10/10 9-10
2 10/10/10 9-10
3 10/10/10 9-10
4 10/10/10 8-9
5 10/11/10 1-2
6 10/11/10 1-2
7 10/12/10 5-6

我只想按范围列出每个日期行的最大值,如下所示:

Date  Range  Total
10/10/10 9-10  3
10/11/10 1-2  2
10/12/10 5-6  1

我想通过使用LINQ来做到这一点,您对如何做到这一点有任何想法吗?

4 个答案:

答案 0 :(得分:6)

我认为这些方面应该有用:

List<MyTable> items = GetItems();
var orderedByMax = from i in items
                   group i by i.Date into g
                   let q = g.GroupBy(i => i.Range)
                            .Select(g2 => new {Range = g2.Key, Count = g2.Count()})
                            .OrderByDescending(i => i.Count)
                   let max = q.FirstOrDefault()
                   select new {
                      Date = g.Key,
                      Range = max.Range,
                      Total = max.Count
                   };

答案 1 :(得分:4)

使用扩展方法:

List<MyTable> items = GetItems();

var rangeTotals = items.GroupBy(x => new { x.Date, x.Range }) // Group by Date + Range
                  .Select(g => new { 
                              Date = g.Key.Date, 
                              Range = g.Key.Range, 
                              Total = g.Count() // Count total of identical ranges per date
                              });

var rangeMaxTotals = rangeTotals.Where(rt => !rangeTotals.Any(z => z.Date == rt.Date && z.Total > rt.Total)); // Get maximum totals for each date

答案 2 :(得分:1)

不幸的是我现在无法测试这个,但试试看:

List<MyTable> items = GetItems();
items.Max(t=>t.Range.Distinct().Count());

答案 3 :(得分:0)

这种方法:
1)按日期分组 2)对于每个日期,按范围分组并计算总计
3)对于每个日期,选择总计最大的项目 4)你最终得到了你的结果

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;
    }
}

根据LINQ in Action(第5.3.3章 - LINQ to Objects是否会损害我的代码的性能?),使用MaxElement扩展方法是最有效的方法之一。我认为性能将是O(4n);一个用于第一个GroupBy,两个用于第二个GroupBy,三个用于Count(),另外四个用于MaxElement中的循环。

DrDro的方法更像是O(n ^ 2),因为它循环列表中每个项目的整个列表。

StriplingWarrior的方法将更接近O(n log n),因为它对项目进行了排序。虽然我承认,在那里可能会有一些我不明白的疯狂魔法。