score:2

Accepted answer

Well, having (let use named tuple to demo):

var resultList = new (string Plate, string Brand, string Model, DateTime InsertDate)[] {
  ("99AA111",  "Tesla",  "S",       new DateTime(2022,01,17, 04,00,00)),
  ("99AA111",  "Tesla",  "S",       new DateTime(2022,01,17, 04,30,00)),
  ("99AA111",  "Tesla",  "S",       new DateTime(2022,01,17, 05,00,00)),
  ("59TA3312", "Nissan", "Skyline", new DateTime(2022,01,17, 04,00,00)),
  ("59TA3312", "Nissan", "Skyline", new DateTime(2022,01,17, 04,30,00)),
  ("129EA512", "Subaru", "Impreza", new DateTime(2022,01,17, 03,30,00)),
};

You can GroupBy twice:

var groupedResult = resultList
  .GroupBy(item => item.Plate)
  .SelectMany(group => group
     .OrderBy(item => item.InsertDate)
     .Select((item, index) => (item: item, index: index / 2))
     .GroupBy(pair => pair.index)
     .Select(g => (
        Plate: g.First().item.Plate,
        Brand: g.First().item.Brand,
        Model: g.First().item.Model,
        FirstPhotoDate: g.First().item.InsertDate,
        SecondPhotoDate: (g.Count() == 1 ? null : (DateTime?)(g.Last().item.InsertDate))
     ))
   );

Let's have a look:

string report = string.Join(Environment.NewLine, groupedResult
  .Select(r => $"{r.Plate,-8} : {r.Brand,-6} : {r.Model,-7} : {r.FirstPhotoDate} : {r.SecondPhotoDate}"));

Console.Write(report);

Outcome:

99AA111  : Tesla  : S       : 17.01.2022 4:00:00 : 17.01.2022 4:30:00
99AA111  : Tesla  : S       : 17.01.2022 5:00:00 : 
59TA3312 : Nissan : Skyline : 17.01.2022 4:00:00 : 17.01.2022 4:30:00
129EA512 : Subaru : Impreza : 17.01.2022 3:30:00 : 

score:0

Here's the cleanest approach I can think of:

var resultList = new (string Plate, string Brand, string Model, DateTime InsertDate)[]
{
    ("99AA111",  "Tesla",  "S",       new DateTime(2022,01,17, 04,00,00)),
    ("99AA111",  "Tesla",  "S",       new DateTime(2022,01,17, 04,30,00)),
    ("99AA111",  "Tesla",  "S",       new DateTime(2022,01,17, 05,00,00)),
    ("59TA3312", "Nissan", "Skyline", new DateTime(2022,01,17, 04,00,00)),
    ("59TA3312", "Nissan", "Skyline", new DateTime(2022,01,17, 04,30,00)),
    ("129EA512", "Subaru", "Impreza", new DateTime(2022,01,17, 03,30,00)),
};

var query =
    from r in resultList
    group (DateTime?)r.InsertDate by new { r.Plate, r.Brand, r.Model } into grs
    from bgrs in grs.OrderBy(x => x).Buffer(2)
    select new
    {
        grs.Key.Plate,
        grs.Key.Brand,
        grs.Key.Model,
        FirstPhotoDate = bgrs.First(),
        SecondPhotoDate = bgrs.Skip(1).Any() ? bgrs.Last() : null,
    };

I used the Buffer operator from Microsoft's System.Interactive NuGet.

That gives me:

query


Related Articles