Ich frage eine Datentabelle ab und ich halte mich fest, wenn ich eine Gruppe von Gruppen auswähle.Geben Sie die ersten x Elemente in einer Gruppe von Gruppen ein
Dieser Code
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);
Gruppen durch Zeitstempel und gibt eine Gruppe von x-Kurven, wobei x = curveid.Count(). Es enthält 5000 Gruppen.
jedoch für jeden Tag kann es mehr als ein Zeitstempel sein.
int nrdays = grouping.GroupBy(z => z.Key.Date).Count();
sagt mir, dass es 255 deutliche Tage sind.
Ich möchte nun zu einer Gruppe diese wieder, aber nicht durch Zeitstempel, sondern von Kalendertag und dann die erste (wie in frühesten) Gruppe für jeden Tag. Ich probierte folgendes:
var grouping2 = grouping.GroupBy(z => z.Key.Date).OrderBy(a => a.Key).Take(curveids.Count);
aber das gibt nur 4 Gruppen zurück und ich verstehe warum nicht? Es sollte 255 Gruppen zurückgeben, von denen jede den gleichen Zeitstempel und x cureids enthält, also x * 255 Datensätze.
Die Datentabelle hat drei Spalten, Zeitstempel (Datetime), CurveID (kurz), Preis (double).
UPDATE
Wie von Herrn Skeet ein vollständiges Beispiel angefordert:
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
ich das Zufallselement entfernt und weiter vereinfacht:
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();
}
Das erwartete Ergebnis ist:
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
Es wäre einfacher, sowohl die Frage zu verstehen als auch Ihnen zu helfen, wenn Sie ein kurzes aber vollständiges Beispiel liefern könnten, das das Problem demonstriert. (Ich würde vorschlagen, eine Liste als Quelldaten zu verwenden, mit regulären Eigenschaften, anstatt einer 'DataTable' ...) –
Ich werde Beispieldaten hinzufügen, aber die Daten kommen aus einer Datenbank und ich lade sie mit sqladapter, so dass es endet in einer Datentabelle – nik
Ja, es endet in einer 'DataTable' in Ihrem echten Code - aber Sie sollten das Problem auf die einfachste Weise demonstrieren. Wenn Sie nicht glauben, dass die 'DataTable' tatsächlich Teil des Problems ist, sollten Sie sie nicht einschließen, da es komplizierter ist, als nur eine' List' zu verwenden. –