Search code examples
c#linqtimelinq-group

Linq Groupby Elapsed Time


I need to group by a list by owner, town and "timeout". I will explain "timeout":

public class Ticket
{
    public int pk { get; set; }
    public string owner { get; set; }
    public string reffering { get; set; }
    public DateTime? created_time { get; set; }
}

And I got a List. I want to create a List> where each sublist contains a list of tickets where created_time is less than 10 seconds.

Here is a sample list of tickets :

pk   owner   reffering   created_time
#1   John    Sam         15/11/2017 11:33:20
#2   John    Sam         15/11/2017 11:33:21
#3   Pat     Jerry       15/11/2017 11:33:27
#4   John    Sam         15/11/2017 11:33:28
#6   Pat     Jerry       15/11/2017 11:33:35
#5   John    Sam         15/11/2017 11:34:00

And I need to get a list of list with

   pk   owner   reffering   created_time
---#1 Sub List ---
    #1   John    Sam         15/11/2017 11:33:20
    #2   John    Sam         15/11/2017 11:33:21
    #4   John    Sam         15/11/2017 11:33:28
---#2 Sub List ---
    #5   John    Sam         15/11/2017 11:34:00
---#3 Sub List ---
    #3   Pat     Jerry       15/11/2017 11:33:27
    #6   Pat     Jerry       15/11/2017 11:33:35

Here my starting code but I can find out how to do this..

List<List<Ticket>> result = tickets.OrderBy(p => p.created_time).GroupBy(p => new { p.owner, p.reffering }).Select(g => g.ToList()).ToList();

Hope some can help especially with the elapsed time.. it makes me crazy!


Solution

  • I'm not quite sure you can do all of this with LINQ, here is my implementation as your references

    var ticketGroups = tickets.OrderBy(x => x.created_time)
                                .GroupBy(x => new { x.owner, x.reffering });
    var tensecondTimespam = new TimeSpan(0, 0, 10);
    var results = new List<List<Ticket>>();
    var ticketTemps = new List<Ticket>();
    
    foreach (var ticketGroup in ticketGroups)
    {
        foreach (var ticket in ticketGroup)
        {
            var currentTicket = ticketTemps.LastOrDefault();
            var isWithinTimeRange = currentTicket == null
                                    || ticket.created_time.Value - currentTicket.created_time.Value <= tensecondTimespam;
    
            if (!isWithinTimeRange)
            {
                results.Add(ticketTemps);
                ticketTemps = new List<Ticket>();
            }
            ticketTemps.Add(ticket);
        }
        if (ticketTemps.Any())
        {
            results.Add(ticketTemps);
            ticketTemps = new List<Ticket>();
        }
    }
    

    The result variable will hold your expected output