如何使用Linq在对象列表中按小时获取最大值

时间:2014-02-06 21:15:26

标签: c# linq

我有一个包含值和日期时间的自定义对象列表。如果可以的话如何使用最大值按小时过滤对象。

因此,按日期和小时对数据进行分组检查对象并且只获得一个小时的数值。

例如我有

class CustomObj
{
  public int Id;
  public int Value;
  public DateTime Date;

}

List<CustomObj> listObj = new List<CustomObj>()

listObj.Add(....100 elemets..)

Id     Value    Date
1      4        2014-02-06 11:41:29.507
2      3        2014-02-06 12:11:29.510
3      4        2014-02-06 12:41:29.510
4      0        2014-02-06 13:11:29.510
5      2        2014-02-06 13:41:29.510
6      0        2014-02-06 14:11:29.510

所以我试图使用linq一个包含ID的项目列表(1,3,5,6)

Ids 1,3,5,6意味着我应该有一个列表,其中包含上表中数据的对象。 我们看起来像这样的结果中的自定义对象列表    Id值日期     1 4 2014-02-06 11:41:29.507     3 4 2014-02-06 12:41:29.510     5 2 2014-02-06 13:41:29.510     6 0 2014-02-06 14:11:29.510

4 个答案:

答案 0 :(得分:2)

获取最长时间的项目:

var objectsWithMaxHour = listObj.GroupBy(o => o.Date.Hour)
                                .OrderByDescending(g => g.Key)
                                .Take(1)
                                .SelectMany(g => g);

按日期分组对象。然后按分组键的值(即按小时)对组进行排序,并取第一组。最后一步是扁平化群组项目。

注意:此查询将返回ID为6的单个对象(因为它是唯一一个小时等于14的对象)。

答案 1 :(得分:1)

如果我没错,你想:

  • 将所有内容分组到一小时(没有分钟和秒),
  • Date
  • 订购每个论坛
  • 选择每个组中最后一个元素的Id

然后这应该工作

var ids = listObj
           .GroupBy(n => new DateTime(n.Date.Year, n.Date.Month, n.Date.Day, n.Date.Hour, 0, 0))
           .Select(g => g.OrderBy(n => n.Date).Last().Id);

答案 2 :(得分:1)

要为数据集中的每个Value获取最大Date.Hour的对象,我们首先要GroupBy Date.Hour,然后为每个组选择对象其Value等于该组中的最大Value,然后最终展平Date.Hour分组以获取Value在所有其他对象中最高的对象列表相同的Date.Hour。在代码中,这看起来像:

var result = list.GroupBy(element => element.Date.Hour)
                 .SelectMany(group => group.Where(element => element.Value == group.Max(obj => obj.Value)));

在您的数据上运行时,初始化为:

        var list = new List<CustomObj>
                       {
                           new CustomObj {Date = DateTime.Parse("2014-02-06 11:41:29.507"), Id = 1, Value = 4},
                           new CustomObj {Date = DateTime.Parse("2014-02-06 12:11:29.510"), Id = 2, Value = 3},
                           new CustomObj {Date = DateTime.Parse("2014-02-06 12:41:29.510"), Id = 3, Value = 4},
                           new CustomObj {Date = DateTime.Parse("2014-02-06 13:11:29.510"), Id = 4, Value = 0},
                           new CustomObj {Date = DateTime.Parse("2014-02-06 13:41:29.510"), Id = 5, Value = 2},
                           new CustomObj {Date = DateTime.Parse("2014-02-06 14:11:29.510"), Id = 6, Value = 0},
                       }; 

查询返回:

Id    Value     Date
1     4         2/6/2014 11:41:29 AM
3     4         2/6/2014 12:41:29 PM
5     2         2/6/2014 1:41:29 PM
6     0         2/6/2014 2:11:29 PM

通过组合@Sergey Berezovskiy和我的,你得到的解决方案比我原来的解决方案更清晰(因为我必须重复两次分组)。在按SelectMany排序小组成员并取一个小组成员后,只需按小时分组元素,然后从分组中Value分组。在代码中,这是:

var result = list.GroupBy(element => element.Date.Hour)
                 .SelectMany(group => group.OrderByDescending(g => g.Key)
                                           .Take(1));

只需要对您的集合进行一次迭代即可获得相同的结果。

答案 3 :(得分:1)

您的所有示例数据都来自一天,因此我不确定您是否要

  1. 无论白天,每小时都会返回一件商品
  2. 为每小时和每天的组合返回单个项目。
  3. 以下是符合第二项要求的代码:

    var lastItemsPerHour = listObj
        .GroupBy(c => new { c.Date.Date, c.Date.Hour },
            (k, ec) => ec.OrderBy(c => c.Date).Last());