Cómo usar LINQ para agrupar y ordenar por cierta columna
ACTUALIZADO: se agregó una nueva columna que combina las columnas Fecha y Hora, que son campos de cadena en la columna DateTimeCombined, que es un campo DateTime
Entonces, lo que debe hacer LINQ es agrupar por columna de nombre y obtener la fila para cada nombre que tenga la fecha + hora más temprana. Luego debería agregar el resto de la fila para el nombre.
DataTable init:
dataT = new DataTable();
dataT.Columns.Add("Date", typeof(string));
dataT.Columns.Add("Time", typeof(string));
dataT.Columns.Add("Day", typeof(string));
dataT.Columns.Add("Name", typeof(string));
dataT.Columns.Add("Place", typeof(string));
dataT.Columns.Add("DateTimeCombined", typeof(DateTime));
dataT.Columns.Add("NameMessage", typeof(string));
Así que aquí está la DataTable inicial (que se recupera por defecto):
Date Time Day Name Place DateTimeCombined NameMessage
6/29/2017 8:30AM MON John Orlance 6/29/2017 8:30:00 AM
6/29/2017 8:40AM MON John Orlance 6/29/2017 8:40:00 AM
6/29/2017 8:50AM MON John Orlance 6/29/2017 8:50:00 AM
6/29/2017 9:10AM MON John Orlance 6/29/2017 9:10:00 AM
6/29/2017 9:20AM MON John Orlance 6/29/2017 9:20:00 AM
6/29/2017 1:00PM MON John Orlance 6/29/2017 1:00:00 PM
6/30/2017 8:30AM TUE John Orlance 6/30/2017 8:30:00 AM
6/30/2017 8:40AM TUE John Orlance 6/30/2017 8:40:00 AM
6/29/2017 8:15AM MON Mike Atlanta 6/29/2017 8:15:00 AM
6/29/2017 8:30AM MON Mike Atlanta 6/29/2017 8:30:00 AM
6/29/2017 8:40AM MON Mike Atlanta 6/29/2017 8:40:00 AM
6/29/2017 9:10AM MON Mike Atlanta 6/29/2017 9:10:00 AM
6/29/2017 9:20AM MON Mike Atlanta 6/29/2017 9:20:00 AM
6/30/2017 8:30AM TUE Mike Atlanta 6/30/2017 8:30:00 AM
6/30/2017 8:40AM TUE Mike Atlanta 6/30/2017 8:40:00 AM
Christine Marion None
Steph Kearney None
6/29/2017 8:30AM MON Jenny Boise 6/29/2017 8:30:00 AM
6/29/2017 8:40AM MON Jenny Boise 6/29/2017 8:40:00 AM
6/29/2017 8:50AM MON Jenny Boise 6/29/2017 8:50:00 AM
6/29/2017 9:10AM MON Jenny Boise 6/29/2017 9:10:00 AM
6/29/2017 9:20AM MON Jenny Boise 6/29/2017 9:20:00 AM
6/30/2017 8:30AM TUE Jenny Boise 6/30/2017 8:30:00 AM
6/30/2017 8:40AM TUE Jenny Boise 6/30/2017 8:40:00 AM
6/29/2017 8:30AM MON Kelly Ardsley 6/29/2017 8:30:00 AM
6/29/2017 8:40AM MON Kelly Ardsley 6/29/2017 8:40:00 AM
6/29/2017 8:50AM MON Kelly Ardsley 6/29/2017 8:50:00 AM
6/29/2017 9:10AM MON Kelly Ardsley 6/29/2017 9:10:00 AM
6/29/2017 9:20AM MON Kelly Ardsley 6/29/2017 9:20:00 AM
6/30/2017 8:30AM TUE Kelly Ardsley 6/30/2017 8:30:00 AM
6/30/2017 8:40AM TUE Kelly Ardsley 6/30/2017 8:40:00 AM
Joseph Houston None
La primera función de LINQ debería ser obtener la anteriorDateTimeCombined
para cada nombre:
6/29/2017 8:30AM MON John Orlance 6/29/2017 8:30:00 AM
6/29/2017 8:15AM MON Mike Atlanta 6/29/2017 8:15:00 AM
6/29/2017 8:30AM MON Jenny Boise 6/29/2017 8:30:00 AM
6/29/2017 8:30AM MON Kelly Ardsley 6/29/2017 8:30:00 AM
La siguiente función debería ser ordenar eso porDateTimeCombined
:
- If `DateTimeCombined` is same, order first by `DateTimeCombined` and then by Name.
- If `DateTimeCombined` is same AND Name is same, order first by `DateTimeCombined` and then by Name and then by Place.
6/29/2017 8:15AM MON Mike Atlanta 6/29/2017 8:15:00 AM
6/29/2017 8:30AM MON Jenny Boise 6/29/2017 8:30:00 AM
6/29/2017 8:30AM MON John Orlance 6/29/2017 8:30:00 AM
6/29/2017 8:30AM MON Kelly Ardsley 6/29/2017 8:30:00 AM
La siguiente función debería ser poner el resto de las filas para cada nombre (la DataTable final debería tener este aspecto):
6/29/2017 8:15AM MON Mike Atlanta 6/29/2017 8:15:00 AM
6/29/2017 8:30AM MON Mike Atlanta 6/29/2017 8:30:00 AM
6/29/2017 8:40AM MON Mike Atlanta 6/29/2017 8:40:00 AM
6/29/2017 9:10AM MON Mike Atlanta 6/29/2017 9:10:00 AM
6/29/2017 9:20AM MON Mike Atlanta 6/29/2017 9:20:00 AM
6/30/2017 8:30AM TUE Mike Atlanta 6/30/2017 8:30:00 AM
6/30/2017 8:40AM TUE Mike Atlanta 6/30/2017 8:40:00 AM
6/29/2017 8:30AM MON Jenny Boise 6/29/2017 8:30:00 AM
6/29/2017 8:40AM MON Jenny Boise 6/29/2017 8:40:00 AM
6/29/2017 8:50AM MON Jenny Boise 6/29/2017 8:50:00 AM
6/29/2017 9:10AM MON Jenny Boise 6/29/2017 9:10:00 AM
6/29/2017 9:20AM MON Jenny Boise 6/29/2017 9:20:00 AM
6/30/2017 8:30AM TUE Jenny Boise 6/30/2017 8:30:00 AM
6/30/2017 8:40AM TUE Jenny Boise 6/30/2017 8:40:00 AM
6/29/2017 8:30AM MON John Orlance 6/29/2017 8:30:00 AM
6/29/2017 8:40AM MON John Orlance 6/29/2017 8:40:00 AM
6/29/2017 8:50AM MON John Orlance 6/29/2017 8:50:00 AM
6/29/2017 9:10AM MON John Orlance 6/29/2017 9:10:00 AM
6/29/2017 9:20AM MON John Orlance 6/29/2017 9:20:00 AM
6/29/2017 1:00PM MON John Orlance 6/29/2017 1:00:00 PM
6/30/2017 8:30AM TUE John Orlance 6/30/2017 8:30:00 AM
6/30/2017 8:40AM TUE John Orlance 6/30/2017 8:40:00 AM
6/29/2017 8:30AM MON Kelly Ardsley 6/29/2017 8:30:00 AM
6/29/2017 8:40AM MON Kelly Ardsley 6/29/2017 8:40:00 AM
6/29/2017 8:50AM MON Kelly Ardsley 6/29/2017 8:50:00 AM
6/29/2017 9:10AM MON Kelly Ardsley 6/29/2017 9:10:00 AM
6/29/2017 9:20AM MON Kelly Ardsley 6/29/2017 9:20:00 AM
6/30/2017 8:30AM TUE Kelly Ardsley 6/30/2017 8:30:00 AM
6/30/2017 8:40AM TUE Kelly Ardsley 6/30/2017 8:40:00 AM
Nota: Si Kelly era John (John apareciendo dos veces), por ejemplo, entonces el grupo Ardsley iría antes que Orlance.
Lo que probé hasta ahora:
var ordered = dataTable.AsEnumerable().OrderBy(en => en.Field<DateTime>("DateTimeCombined")).CopyToDataTable();
Actualizar:
var ordered = dataTable.AsEnumerable()
.OrderBy(en => en.Field<DateTime>("DateTimeCombined"))
.GroupBy(en1 => en1.Field<string>("Name")).ToList();
Solo me da el nombre solamente.
Actualizar:
var q = dataTable.AsEnumerable()
.GroupBy(item => item.Field<string>("Name"))
.SelectMany(grouping => grouping.Take(1))
.OrderBy(item => item.Field<DateTime>("CombinedDateTime"))
.ThenBy(item => item.Field<string>("Name"))
.ThenBy(item => item.Field<string>("Place"))
.CopyToDataTable();
Lo anterior funciona como se esperaba:
6/29/2017 8:15AM MON Mike Atlanta 6/29/2017 8:15:00 AM
6/29/2017 8:30AM MON Jenny Boise 6/29/2017 8:30:00 AM
6/29/2017 8:30AM MON John Orlance 6/29/2017 8:30:00 AM
6/29/2017 8:30AM MON Kelly Ardsley 6/29/2017 8:30:00 AM
pero solo si tomo la primera fila de cada grupo (por nombre). Si tomo todo por grupo, las filas se mezclan. ¿Cómo puedo ahora, agregar el resto deMike's
filas después de la fila de Mike, agregue el resto deJenny's
filas después de la fila de Jenny, y así sucesivamente? ¿Se puede hacer esto en el mismo LINQ?