开发者

Group-by specific time ranges in LINQ

开发者 https://www.devze.com 2023-03-23 02:31 出处:网络
I have a List<Advertisement> where Advertisement contains public DateTime StartDate { get; set; }

I have a

List<Advertisement> 

where Advertisement contains

public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }

What I want to do is group the elements in the List<Advertisement> by three specific time ranges using a GroupBy. The three time ranges are as follows:

  • x => x.StartDate > DateTime.Now.Subtract(TimeSpan.FromDays(1))
  • x => x.StartDate > DateTime.Now.Subtract(TimeSpan.FromDays(7))
  • x => x.StartDate > DateTime.Now.Subtract(TimeSpan.FromDays(365))

So elements with start date in the last day, elements with start date in the last week and elements with start date in the last year.

The group of elements from the last year should include those elements with a start date in the last week and day. And the group of elements from the last week should include those elements from the last day.

I just cant se开发者_运维问答em to think how to do this. Cheers.


As you want each group to also include the previous groups contents (eg lastweek includes last day) I've constructed a union query

var today=items.Where(l=>l.StartDate>DateTime.Now.Subtract(TimeSpan.FromDays(1)));
var lastweek=items.Where(l=>l.StartDate>DateTime.Now.Subtract(TimeSpan.FromDays(7)));
var lastyear=items.Where(l=>l.StartDate>DateTime.Now.Subtract(TimeSpan.FromDays(365)));


var result = today.Select(d => new { Group="Last Day",item=d})
                  .Union(lastweek.Select(w => new {Group="Last Week",item=w}))
                  .Union(lastyear.Select(y => new {Group="Last Year",item=y}))
                  .GroupBy (l => l.Group,l=>l.item);

How this query works is it creates 3 sub queries to select the relevant data. Each query then uses a select operator to select the match group name and the original item projected into an anonymous object. (Basically creates a new object with the groupname as one property and the original Item as another). I then use union to combine the multiple results together in one big list. (Union has the added property that it strips duplicates, but there shouldn't be any). Once I have the big list I can then Group by the groupname, the second parameter basically puts the orginal item back in as the group value.


You can create a method (or extension) wich will return some value specific to a group, and then make grouping by it.


One method may be to write an extension method which returns the category that it falls into.

public static int GetCategory(this Advertisement advert)
{
    if(x.StartDate > DateTime.Now.Subtract(TimeSpan.FromDays(1)))
    {
        return 1;
    }
etc...
}

then you can group by the GetCategory property. It is probably better to return an Enum instead of an integer.

0

精彩评论

暂无评论...
验证码 换一张
取 消