简体   繁体   English

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

[英]How can I get the maximum value by hour in a list of object using Linq

I have a list of custom object that have values and datetimes. 我有具有值和日期时间的自定义对象的列表。 If is possible to do How can I filter the object with maximum values by hours. 如果可能的话,如何按小时过滤最大值的对象。

So grouping the data by date and hours check the objects and get only one by hour witch has the higher value. 因此,按日期和小时对数据进行分组会检查对象,并且每小时仅获取一个具有较高价值的对象。

For instance I have 例如我有

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

So I am trying to get using linq a list that containing the items with Ids (1,3,5,6) 所以我试图使用linq一个包含ID(1,3,5,6)项的列表

Ids 1,3,5,6 means that I should have a list with the object that from the data of the table above. ID 1、3、5、6表示我应该有一个包含上表数据的对象的列表。 list of custom objects as a result in a table we look like this 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 表格中显示的自定义对象列表,我们看起来像这样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

Getting items with max hour: 以最大小时数获取物品:

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

Group objects by hour of date. 按小时将对象分组。 Then sort groups by value of grouping key (ie by hour) and take first group. 然后按分组键的值对分组进行排序(即按小时),然后进行第一个分组。 Last step is flattening group items. 最后一步是展平组项目。

NOTE: This query will return single object with id 6 (because it's the only object with hour equal to 14). 注意:此查询将返回ID为6的单个对象(因为它是小时等于14的唯一对象)。

If I am not wrong and you want to: 如果我没看错,而您想:

  • group by everything down to an hour (without minutes ans seconds), 将所有内容归类到一个小时(不包括分钟和秒),
  • order each group by Date Date排序每个组
  • select Id of last element in each group 选择每个组中最后一个元素的Id

then this should work 那么这应该工作

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

To get the object with the maximum Value for each Date.Hour in the dataset, we'll first want to GroupBy Date.Hour , then for each group select the object whose Value is equal to the maximum Value in that group, then finally flatten the Date.Hour grouping to get a list of objects whose Value is the highest among all other objects with the same Date.Hour . 要获得最大的目标Value为每个Date.Hour数据集中,我们首先想GroupBy Date.Hour ,然后为每个组选择其对象Value等于最大Value在该组中,最后压平将Date.Hour分组以获取对象列表,其Value在所有其他具有相同Date.Hour对象中是最高的。 In code, this looks like: 在代码中,这看起来像:

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

When run on your data, initialized like: 对数据运行时,初始化如下:

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

The query returns: 查询返回:

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

By combining @Sergey Berezovskiy 's and mine, you get a solution much cleaner than my original solution (since mine must iterate over the grouping twice). 通过结合使用@Sergey Berezovskiy和我的解决方案,您得到的解决方案比我原来的解决方案干净得多(因为我的解决方案必须对分组进行两次迭代)。 Simply group the elements by hour like before and SelectMany from the groupings after ordering the group members by Value and taking one. 像以前一样简单地按小时对元素进行分组,然后按Value对组成员进行排序并取一个,然后从分组中按SelectMany进行分组。 In code, this is: 在代码中,这是:

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

Which will give the same result while only requiring a single iteration over your collection. 这将产生相同的结果,而只需要对集合进行一次迭代。

All of your example data are from one day, so I'm not sure if you want to 您的所有示例数据都来自一天,因此我不确定您是否要

  1. return a single item for each hour regardless of day 每小时返回一个项目,而不考虑日期
  2. return a single item for each combination of hour and day. 按小时和日期的每种组合返回一个项目。

Here is code that will meet the second requirement: 这是满足第二个要求的代码:

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