Estoy lidiando con un problema probablemente simple pero difícil para mí. Estoy tomando fotos de autos estacionados y las guardo con la placa del auto y la marca de tiempo. El mismo auto podría ser fotografiado varias veces durante el día.
Data de muestra
| Plato | Marca | Modelo | Insertar la fecha |
|---|---|---|---|
| 99AA111 | tesla | S | 2022-01-17 04:00:00 |
| 99AA111 | tesla | S | 2022-01-17 04:30:00 |
| 99AA111 | tesla | S | 2022-01-17 05:00:00 |
| 59TA3312 | nissan | Horizonte | 2022-01-17 04:00:00 |
| 59TA3312 | nissan | Horizonte | 2022-01-17 04:30:00 |
| 129EA512 | subaru | Impreza | 2022-01-17 03:30:00 |
Lo que estoy tratando de lograr es;
| Plato | Marca | Modelo | PrimeraFotoFecha | SegundaFotoFecha |
|---|---|---|---|---|
| 99AA111 | tesla | S | 2022-01-17 04:00:00 | 2022-01-17 04:30:00 |
| 99AA111 | tesla | S | 2022-01-17 05:00:00 | - |
| 59TA3312 | nissan | Horizonte | 2022-01-17 04:00:00 | 2022-01-17 04:30:00 |
| 129EA512 | subaru | Impreza | 2022-01-17 03:30:00 | - |
se me ha ocurrido;
var groupedResult = resultList.GroupBy(f => f.Plate).Select(f => new ResultListView { Plate = f.Key, FirstDate = f.Min(f => f.InsertDate), SecondDate = f.Max(f => f.InsertDate), Brand = f.FirstOrDefault().Brand, Model = f.FirstOrDefault().Model, TimeDifference = (f.Max(f => f.InsertDate) - f.Min(f => f.InsertDate)).TotalMinutes });Pero como es obvio en el código, solo me da el primer y el último registro pero no como esperaba. Estoy tratando de agrupar por platos y si el mismo plato va más de una vez, emparejarlo con el siguiente. si solo hay una foto o tres fotos, la segunda fecha debe ser nula.
Por supuesto, se podrían aplicar diferentes lógicas, pero creo que esta es una forma más clara.
Pensé en ese bucle dentro del resultado agrupado. Tome el primero y el segundo y salte dos. Pero esto no es lo que estoy buscando.
Gracias por tu ayuda.
Bueno, teniendo (vamos a usar la tupla con nombre para la demostración):
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)), }; Puedes GroupBy dos veces :
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)) )) );Echemos un vistazo:
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);Salir:
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 :Aquí está el enfoque más limpio que se me ocurre:
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, }; Usé el operador Buffer de System.Interactive NuGet de Microsoft.
Eso me da: