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)
Ids 1,3,5,6 means that I should have a list with the object that from the data of the table above. 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
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).
If I am not wrong and you want to:
Date
Id
of last element in each group 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
. 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). Simply group the elements by hour like before and SelectMany
from the groupings after ordering the group members by Value
and taking one. 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
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());
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.