I have the following model:
public class Entry
{
public int UseraccountId { get; set; }
public int CompanyId { get; set; }
public DateTime CreationDate { get; set; }
public string Target { get; set; }
public string Message { get; set; }
}
And a list with a lot of entries:
List<Entry> entries = ... //get all entries.
Example:
I'd now like row 2 and 3 to be grouped because they have the same UserId, same CompanyId, same target and almost (and this is the difficult part), let's say in a range of 5 seconds, the same date time.
After grouping my list should look like this:
Is there any easy approach for this problem? Any advices? I bet Linq will help me around but I'm not sure how.
Edit: Thank you all for your feedback. I decided to change the design and to ensure that the datetime is now really the same. So grouping with linq is now very easy.
As @dtb menitons, grouping by "close" is difficult because you can end up with a bigger "bucket" than you intended. For example, If you have 100 entries that are created 4 seconds apart from each other, grouping items that are within 5 seconds of the "next" item would put all of them in one bucket!
If, however, you want to round the creating date to the nearest, say, 5 seconds and then group, you could use:
TimeSpan ts = new TimeSpan(0, 0, 5); // 5 seconds
entries.GroupBy(i => new {
UserId = i.UserId,
CompanyId = i.CompanyId,
Target = i.Target,
RoundedTime = DateTime.MinValue.AddTicks(
(long)(Math.Round((decimal)i.CreationDate.Ticks / ts.Ticks) * ts.Ticks)
) ;
))
.Select(g => new {
UserId = g.Key.UserId,
CompanyId = g.Key.CompanyId,
Target = g.Key.Target,
RoundedTime = g.Key.RoundedTime,
Message = string.Join(", ",g.Select(i=> i.Message).ToArray())
} );
That will group by items that are rounded to the nearest 5 seconds - it's possible that two items one second apart will be in different buckets, but you don't have the problem with cummutativity that your stated requirement has.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With