如何通过linq查询对组中的元素进行排序,然后选择第一个?

时间:2016-08-11 14:16:35

标签: c# linq group-by

我有一组包含类型,日期和值的数据。

我想按类型分组,并且对于每组中的每组值,我想选择具有最新日期的那一组。

这是一些有效的代码并给出了正确的结果,但我想在一个linq查询中而不是在迭代中完成所有操作。任何想法如何我可以用纯粹的linq查询获得相同的结果......?

using System;
using System.Linq;
using System.Collections.Generic;

public class Program {

    public static void Main() {

        var mydata = new List<Item> {
            new Item { Type = "A", Date = DateTime.Parse("2016/08/11"), Value = 1 },
            new Item { Type = "A", Date = DateTime.Parse("2016/08/12"), Value = 2 },
            new Item { Type = "B", Date = DateTime.Parse("2016/08/20"), Value = 3 },
            new Item { Type = "A", Date = DateTime.Parse("2016/08/09"), Value = 4 },
            new Item { Type = "A", Date = DateTime.Parse("2016/08/08"), Value = 5 },
            new Item { Type = "C", Date = DateTime.Parse("2016/08/17"), Value = 6 },
            new Item { Type = "B", Date = DateTime.Parse("2016/08/30"), Value = 7 },
            new Item { Type = "B", Date = DateTime.Parse("2016/08/18"), Value = 8 },
        };

        var data = mydata.GroupBy(_ => _.Type);

        foreach (var thing in data) {

            #region 

            // How can I remove this section and make it part of the group by query above... ?          
            var subset = thing.OrderByDescending(_ => _.Date);
            var top = subset.First();

            #endregion

            Console.WriteLine($"{thing.Key} {top.Date.ToString("yyyy-MM-dd")} {top.Value}");

        }           
    }

    public class Item {

        public string Type {get;set;}
        public DateTime Date {get;set;}
        public int Value {get;set;}

    }   
}

// Output:
//   A 2016-08-12 2
//   B 2016-08-30 7
//   C 2016-08-17 6

4 个答案:

答案 0 :(得分:7)

使用select获取FirstOrDefault(或First - 因为您不会获得null的分组)有序降序:

var data = mydata.GroupBy(item => item.Type)
                 .Select(group => group.OrderByDescending(x => x.Date)
                 .FirstOrDefault())
                 .ToList();

SelectMany以及Take(1)

var data = mydata.GroupBy(item => item.Type)
                 .SelectMany(group => group.OrderByDescending(x => x.Date)
                 .Take(1))
                 .ToList();

答案 1 :(得分:2)

您可以Select订购组的第一个元素:

var topItems = mydata.GroupBy(item => item.Type)
                     .Select(group => group.OrderByDescending(item => item.Date).First())
                     .ToList();

topItems现在是List<Item>,仅包含每Type的热门商品。

您也可以Dictionary<string,Item>Type字符串映射到Item的顶部Type来检索它:

var topItems = mydata.GroupBy(item => item.Type)
                     .ToDictionary(group => group.Key,
                              group => group.OrderByDescending(item => item.Date).First());

答案 2 :(得分:2)

var data = mydata.GroupBy(
    item => item.Type,
    (type, items) => items.OrderByDescending(item => item.Date).First());

foreach (var item in data)
{
    Console.WriteLine($"{item.Type} {item.Date.ToString("yyyy-MM-dd")} {item.Value}");
}

答案 3 :(得分:1)

按类型分组,对于每个组,按日期降序排序并选择第一个(最新的)。

mydata.GroupBy(i => i.Type).Select(g => g.OrderByDescending(i => i.Date).First());