Statistikdaten auswerten - CustomClass.DateTime - nach Monaten und Jahren sortieren
-
Hi ...
Ich suche nach einer Lösung für folgendes Problem, komme aber auch nach Tagen einfach nicht weiter. Bestimmt habt ihr eine Idee dazu.
Folgende Klasse:
class DataSubClass : DependencyObject { public event PropertyChangedEventHandler PropertyChanged; #region *** Variablen *** public static readonly DependencyProperty datumProperty = DependencyProperty.Register("datum", typeof(DateTime), typeof(DataSubClass), new PropertyMetadata(new DateTime())); ... ...
...dient mir zum halten von Statistikdaten.
Das ganze befindet sich zur Auswertung in einer Collection<DataSubClass>. Dem User möchte ich nun wie üblich die Möglichkeit geben die Daten taggenau, nach Monaten und Jahren anzuzeigen.
Taggenau und Jahresansicht stellen hierbei kein Problem da, aber die verdammte Monatsansicht bekomme ich einfach nicht hin.
Mein Ziel ist es, nach der Auswertung eine Liste von Jahren zu erhalten, in welcher die Monate mit erfassten Daten und die Daten selber vorliegen. Also so:
2011
---Januar
-----List<DataSubClass>
---Februar
-----List<DataSubClass>
...
2012
---Januar
-----List<DataSubClass>
---Februar
-----List<DataSubClass>Bei meiner Jahresauswertung sieht das ganze so aus:
case ShowingMode.Years: { //vorhandene Jahre erfassen List<int> yearList = new List<int>(); List<KeyValuePair<int, List<DataSubClass>>> yearDataList = new List<KeyValuePair<int, List<DataSubClass>>>(); //Daten nach Jahren zusammenfassen foreach (DataSubClass dsc in ((DataClass)currentDataClass).datenBuffer) { //Jahr erstellen da es noch nicht existiert if (yearList.Contains(dsc.datum.Year) == false) { yearList.Add(dsc.datum.Year); yearDataList.Add(new KeyValuePair<int, List<DataSubClass>>(dsc.datum.Year, new List<DataSubClass>())); } //Index des Jahrs in beiden Listen int yearIndex = yearList.IndexOf(dsc.datum.Year); yearDataList[yearIndex].Value.Add(dsc); } //Endgültige Daten berechnen lassen foreach (KeyValuePair<int, List<DataSubClass>> yearData in yearDataList) { verlust = 0; foreach (DataSubClass dsub in yearData.Value) verlust = verlust + DataClass.calcDurchschnittVerlust(((DataClass)currentDataClass), dsub); verlust = (verlust / yearData.Value.Count); //neuen Point zur Serie hinzufügen dataColl.Add(new StatistikHelper { DataPoint = new Point(dx, verlust), Digitvalue = verlust, DateVariant = "Jahr: " + yearData.Key.ToString() + " " + Math.Round(verlust, 2) + " %" }); dx = dx + (sizeOfOneXElement.Width / 10); } return dataColl; }
Ich hoffe ihr versteht was ich erreichen möchte und bringt mich auf die richtige Idee !?
-
Ein anderer Ansatz wäre, dieses Problem via Linq zu lösen, d.h. du könntest SQL ähnliche Abfragen auf deiner Enumeration durchführen und über das Ergebnis einfach drüber iterieren.
Beispiel:
using System.Linq; // example list List<DateTime> dates = new List<DateTime>(); for (int i = 0; i < 365; i++) dates.Add(DateTime.Now.AddDays(i)); // query with lambda expression var months = dates.AsEnumerable<DateTime>().Where(m => m.Month == 1 && m.Year == 2013); foreach(var month in months) Console.WriteLine(month.ToString());
http://msdn.microsoft.com/de-de/library/vstudio/bb336768(v=vs.100).aspx
-
Du, das hat mir geholfen. Das ganze sieht nun so aus und funzt:
case ShowingMode.Months: { //Bei der Monatsansicht müssen die Monate auch bei vorhandensein von Daten //von mehreren Jahren richtig einsortiert werden List<int> yearlist = new List<int>(); foreach (DataSubClass dsc in ((DataClass)currentDataClass).datenBuffer) if (yearlist.Contains(dsc.datum.Year) == false) yearlist.Add(dsc.datum.Year); foreach (int yearItem in yearlist) { var years = ((DataClass)currentDataClass).datenBuffer.AsEnumerable<DataSubClass>().Where(m => m.datum.Year == yearItem); List<int> monthlist = new List<int>(); foreach (var year in years) if (monthlist.Contains(year.datum.Month) == false) monthlist.Add(year.datum.Month); foreach (int monthItem in monthlist) { var months = years.AsEnumerable<DataSubClass>().Where(m => m.datum.Month == monthItem); foreach (var month in months) { verlust = 0; verlust = verlust + DataClass.calcDurchschnittVerlust(((DataClass)currentDataClass), month); verlust = (verlust / months.Count()); } dataColl.Add(new StatistikHelper { DataPoint = new Point(dx, verlust), Digitvalue = verlust, DateVariant = Enum.GetName(typeof(Monate), monthItem) + " " + yearItem }); dx = dx + (sizeOfOneXElement.Width / 10); } } verlust = 0; return dataColl; }
Könnte man das noch vereinfachen ?
-
foreach (var month in months) { verlust = 0; verlust = verlust + DataClass.calcDurchschnittVerlust(((DataClass)currentDataClass), month); verlust = (verlust / months.Count()); }
Das läßt sich sicherlich noch vereinfachen, aber vorallem ergibt dies überhaupt keinen Sinn (denn so berechnest du immer nur den Verlust des letzten Monats...).
Edit: lagere den gesamten Code auch am besten in eine eigene Methode aus und schreibe dir ein paar Tests dafür, damit du dir sicher sein kannst, daß die Methode das tut, was du erwartest.
-
Oh mensch, das habe ich übersehen.