Ich bin nicht ganz sicher, wie Sie diese Daten wollen, aber man konnte es in eine anonyme Art projizieren:
var metersFirstAndLastReading = meters.Select(m => new
{
Meter = m,
FirstReading = m.readings.OrderBy(r => r.time).First(),
LastReading = m.readings.OrderBy(r => r.time).Last()
});
Anschließend können Sie Ihre Ergebnisliste wie folgt lesen (in diesem Beispiel nur als Illustration zu verstehen ist):
foreach(var currentReading in metersFirstAndLastReading)
{
string printReadings = String.Format("Meter id {0}, First = {1}, Last = {2}",
currentReading.Meter.id.ToString(),
currentReading.FirstReading.time.ToString(),
currentReading.LastReading.time.ToString());
// Do something...
}
Eine andere Möglichkeit wäre, Eigenschaften in Meter schaffen, welche die ersten und letzten Messwerte dynamisch zurück:
public class Meter
{
public int id;
public List<Reading> readings;
public Reading FirstReading
{
get
{
return readings.OrderBy(r => r.time).First();
}
}
public Reading LastReading
{
get
{
return readings.OrderBy(r => r.time).Last();
}
}
}
EDIT: Ich habe die Frage ein wenig missverstanden.
Hier ist die Implementierung ist es, die ersten und letzten Ablesungen für einen Zähler einschließlich einen Datumsbereich (unter der Annahme meterIdList
eine ICollection<int>
von IDs und begin
und end
wird den angegebenen Datumsbereich)
var metersFirstAndLastReading = meters
.Where(m => meterIdList.Contains(m.id))
.Select(m => new
{
Meter = m,
FirstReading = m.readings
.Where(r => r.time >= begin && r.time <= end)
.OrderBy(r => r.time)
.FirstOrDefault(),
LastReading = m.readings
.Where(r => r.time >= begin && r.time <= end)
.OrderByDescending(r => r.time)
.FirstOrDefault()
});
um zu bestimmen, Sie können jetzt keine Eigenschaften mehr verwenden (da Sie Parameter angeben müssen), so dass die Methoden problemlos als Alternative funktionieren:
public class Meter
{
public int id;
public List<Reading> readings;
public Reading GetFirstReading(DateTime begin, DateTime end)
{
var filteredReadings = readings.Where(r => r.time >= begin && r.time <= end);
if(!HasReadings(begin, end))
{
throw new ArgumentOutOfRangeException("No readings available during this period");
}
return filteredReadings.OrderBy(r => r.time).First();
}
public Reading GetLastReading(DateTime begin, DateTime end)
{
var filteredReadings = readings.Where(r => r.time >= begin && r.time <= end);
if(!HasReadings(begin, end))
{
throw new ArgumentOutOfRangeException("No readings available during this period");
}
return filteredReadings.OrderBy(r => r.time).Last();
}
public bool HasReadings(DateTime begin, DateTime end)
{
return readings.Any(r => r.time >= begin && r.time <= end);
}
}
Haben Sie versucht, 'Queryable.First()' und 'Queryable.Last (')? –
Ja, meine Lösung ist für jeden Meter und Zeitraum, First() und Last() zu nehmen - aber das berücksichtigt nicht die Tatsache, dass ich für alle Meter den gleichen Zeitraum betrachte. vielleicht wäre eine Art Gruppierung hier effizienter? –