Я запрашиваю данные, и я, похоже, придерживаюсь выбора группы групп.Возврат первых элементов x в группе групп
Этот код
var grouping = table.AsEnumerable()
.Where(x => curveids.Contains(x.Field<short>("CurveID")) && x.Field<DateTime>("Timestamp").Hour >= hour && x.Field<DateTime>("Timestamp").Hour < (hour + 1))
.GroupBy(x => x.Field<DateTime>("Timestamp")).Where(x => x.Select(y => y["CurveID"]).Count() == curveids.Count);
группы по временной метки и возвращает группу кривых х, где х = curveid.Count(). Он содержит 5000 групп.
Однако на каждый день может быть более одной отметки времени.
int nrdays = grouping.GroupBy(z => z.Key.Date).Count();
говорит, что есть 255 отдельных дней.
Теперь я хотел бы сгруппировать это, но не по времени, а по календарному дню, а затем взять первую (как раньше) группу за каждый день. Я пробовал:
var grouping2 = grouping.GroupBy(z => z.Key.Date).OrderBy(a => a.Key).Take(curveids.Count);
но это только возвращает 4 группы, и я не понимаю почему? Он должен возвращать 255 групп, каждый из которых содержит одну и ту же метку времени и x кривые, поэтому x * 255 наборов записей.
В datatable есть 3 столбца, временная метка (DateTime), криваяID (короткая), цена (двойная).
ОБНОВЛЕНИЕ
В соответствии с просьбой г-н тарелочкам полный пример:
public class listprx
{
public DateTime timestamp;
public int curveID;
public double prx;
}
static void Main(string[] args)
{
var data = new List<listprx>();
// populating data
for (int i = 0; i < 50000; i++)
{
Random rand = new Random(i);
var tempdt = new DateTime(2016, rand.Next(1, 12), rand.Next(1, 29), rand.Next(1, 23), rand.Next(1, 59), 0);
if(i % 3 == 0)
{
data.Add(new listprx { timestamp = tempdt, curveID = 1, prx = rand.Next(1,50)});
data.Add(new listprx { timestamp = tempdt, curveID = 2, prx = rand.Next(1, 50) });
}
else if (i % 5 == 0)
{
data.Add(new listprx { timestamp = tempdt, curveID = 1, prx = rand.Next(1, 50) });
}
else
{
data.Add(new listprx { timestamp = tempdt, curveID = 1, prx = rand.Next(1, 50) });
data.Add(new listprx { timestamp = tempdt, curveID = 2, prx = rand.Next(1, 50) });
data.Add(new listprx { timestamp = tempdt, curveID = 3, prx = rand.Next(1, 50) });
}
}
// setting hour criteria
int hour = 16;
int nrcurves = 3;
// grouping by timestamp and only take those where all curves are there, (as close to the desired time as possible
var grouping = data.Where(x => x.timestamp.Hour >= hour && x.timestamp.Hour < (hour + 1))
.GroupBy(x => x.timestamp).Where(x => x.Select(y => y.curveID).Count() == nrcurves);
// Grouping by day and take only the time stamp that is closest to the hour
// this fails
var grouping2 = grouping.GroupBy(z => z.Key.Date).OrderBy(a => a.Key).Take(nrcurves);
Console.WriteLine("Nr of timestamps with all curves {0}, nr of days {1}, nr of groups in second group {2}, expected same as nr days"
, grouping.Count(), grouping.GroupBy(z => z.Key.Date).Count(), grouping2.Count());
Console.ReadLine();
}
UPDATE 2
Я удалил случайный элемент и упрощен далее:
public class listprx
{
public DateTime timestamp;
public int curveID;
}
static void Main(string[] args)
{
var data = new List<listprx>();
// populating data
var tempdt = new DateTime(2016, 4, 6, 16, 1, 0);
for (int i = 0; i < 4; i++)
{
if (i == 2)
{
tempdt = tempdt.AddDays(1);
}
if(i % 2 == 0)
{
data.Add(new listprx { timestamp = tempdt, curveID = 1});
}
else
{
data.Add(new listprx { timestamp = tempdt, curveID = 1});
data.Add(new listprx { timestamp = tempdt, curveID = 2});
}
tempdt = tempdt.AddMinutes(i+1);
}
// setting hour criteria
int hour = 16;
int nrcurves = 2;
//grouping by timestamp and only take those where all curves are there, (as close to the desired time as possible
var grouping = data.Where(x => x.timestamp.Hour >= hour && x.timestamp.Hour < (hour + 1))
.GroupBy(x => x.timestamp).Where(x => x.Select(y => y.curveID).Count() == nrcurves);
//Grouping by day and take only the time stamp that is closest to the hour
//this fails
var grouping2 = grouping.GroupBy(z => z.Key.Date).OrderBy(a => a.Key).Take(nrcurves);
Console.WriteLine("Nr of timestamps with all curves {0}, nr of days {1}, nr of groups in second group {2}, expected same as nr days"
, grouping.Count(), grouping.GroupBy(z => z.Key.Date).Count(), grouping2.Count());
Console.ReadLine();
}
Ожидаемый конечный результат:
Timestamp CurveID
------------------------
6/4/16 16:02 1
6/4/16 16:02 2
7/4/16 16:06 1
7/4/16 16:06 2
Было бы проще понять и ответить на вопрос, если бы вы могли предоставить короткий, но полный пример, демонстрирующий проблему. (Я бы предложил использовать список в качестве исходных данных, с регулярными свойствами, а не с 'DataTable' ...) –
Я добавлю примеры данных, но данные поступают из базы данных, и я загружаю его с помощью блока sqladapter, чтобы он заканчивался в datatable – nik
Да, это заканчивается в «DataTable» в вашем реальном коде, но вы должны продемонстрировать проблему самым простым способом. Если вы не считаете, что «DataTable» на самом деле является частью проблемы, вы не должны включать его, поскольку это сложнее, чем просто использовать «Список». –