繁体   English   中英

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

[英]How can I get the maximum value by hour in a list of object using 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)项的列表

ID 1、3、5、6表示我应该有一个包含上表数据的对象的列表。 表格中显示的自定义对象列表,我们看起来像这样Id Value Date 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

以最大小时数获取物品:

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

按小时将对象分组。 然后按分组键的值对分组进行排序(即按小时),然后进行第一个分组。 最后一步是展平组项目。

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

如果我没看错,而您想:

  • 将所有内容归类到一个小时(不包括分钟和秒),
  • 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);

要获得最大的目标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和我的解决方案,您得到的解决方案比我原来的解决方案干净得多(因为我的解决方案必须对分组进行两次迭代)。 像以前一样简单地按小时对元素进行分组,然后按Value对组成员进行排序并取一个,然后从分组中按SelectMany进行分组。 在代码中,这是:

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

这将产生相同的结果,而只需要对集合进行一次迭代。

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

  1. 每小时返回一个项目,而不考虑日期
  2. 按小时和日期的每种组合返回一个项目。

这是满足第二个要求的代码:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM