Liste mit mehreren gleichen Elementen - Wie Sortieren? [Achtung Anfänger]

  • C#

Es gibt 12 Antworten in diesem Thema. Der letzte Beitrag () ist von JonathanPB.

    Liste mit mehreren gleichen Elementen - Wie Sortieren? [Achtung Anfänger]

    Moin,

    ich bin nicht nur neu in dem Forum, sondern auch unerfahren mit C# und Programmieren generell - ich bitte euch daher, etwas Geduld mit mir zu haben :D

    Trotz alledem habe ich mich daran gewagt eine App zu Programmieren. Diese soll Daten vom Robert-Koch-Institut herunterladen und auswerten.
    Dazu habe ich Klassen angelegt, welche ich zum Deserialisieren der JSON Daten nutze. Das sieht wie folgt aus:

    C#-Quellcode

    1. public class Attributes
    2. {
    3. public int AnzahlFall { get; set; }
    4. public long Meldedatum { get; set; }
    5. }
    6. public class Report
    7. {
    8. public Attributes attributes { get; set; }
    9. public long getReportDate()
    10. {
    11. return attributes.Meldedatum;
    12. }
    13. public int getNewInfect()
    14. {
    15. return attributes.AnzahlFall;
    16. }
    17. }
    18. public class Caselist
    19. {
    20. public List<Report> features { get; set; }
    21. }


    Diese Struktur ist mir von den JSON-Daten vorgegeben.

    Ich möchte mit diesen Daten nun einen Graphen erstellen, der auf der x-Achse Die Zeit und auf der Y-Achse Die Neuinfektionen des Tages angibt.
    Nun ist es aber so, dass - bedingt durch den Datensatz - zwei Reports das selbe Meldedatum enthalten können. (Caselist.features.attributes.Meldedatum)
    Folgende Schleife habe ich bereits Programmiert:

    C#-Quellcode

    1. int newinfect = 0;
    2. for (int i = 0; i != d.features.Count; i++)
    3. {
    4. date = (UnixTimeStampToDateTime(d.features[i].attributes.Meldedatum).ToOADate());
    5. s_newinfectperday.Points.Add(new DataPoint(date, newinfect)); // fügt die Daten zur Tabelle hinzu
    6. if (UnixTimeStampToDateTime(d.features[i].attributes.Meldedatum).ToOADate().Equals(date))
    7. {
    8. newinfect = d.features[i].attributes.AnzahlFall;
    9. }
    10. }

    Mit der Funktion "UnixTimeStampToDateTime" berechne ich aus dem UnixTimeStamp ein System.DateTime Objekt.

    Ziel war es, wie gesagt, für den Tag (also 1 - 365), den ich als Parameter übergebe, alle Neuinfektionen zu berechnen.
    Jedoch erhalte ich diesen Graphen, in dem die Anzahl an Neuinfektionen jedes einzelnen Reports dargestellt wird:


    Ich kann meine eigene Arbeit langsam selbst nicht mehr überblicken und habe mir bereits schon Stunden den Kopf darüber zerbrochen, deswegen hoffe ich, dass mir ein/e erfahrene/r Coder/in aushelfen kann!

    Ich danke schonmal für eure Zeit!

    MfG,
    Jonathan

    Thema verschoben, Quellcode formatiert ~ EaranMaleasi

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „EaranMaleasi“ ()

    Willkommen im Forum @JonathanPB ^^

    Zu deiner Info, auch wenn das Forum VB-Paradise lautet, bedeutet das nicht ,dass C# zu den "anderen" Sprachen gehört. VB.NET und C# nutzen beide das .NET Framework, .NET Core und in Zukunft .NET. Du kannst also deine Fragen zu C# ebenso in die entsprechenden Unterforen posten. Ich habe diesen Thread bereits für dich in die korrekte Kategorie verschoben.
    Des weiteren möchte ich dich darauf hinweisen, dass es unter Erweiterte Antwort die Möglichkeit gibt, Bilder direkt ins Forum hochzuladen. So musst du nicht den Weg über externe Hoster gehen.

    Nun zu deinem Thema, welche Datenquelle benutzt du denn genau?
    @JonathanPB Ebenfalls: Willkommen im Forum. :thumbup:
    Wie sehen denn die heruntergeladenen Daten aus?
    Kannst Du mal ein paar Datensätze posten?
    Wie sollen zwei Datensätze desselben Datums behandelt werden?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @EaranMaleasi
    Erstmal: Danke für die Infos, werde ich in Zukunft beachten ;)

    Nun zum Thema:

    EaranMaleasi schrieb:



    Nun zu deinem Thema, welche Datenquelle benutzt du denn genau?

    Ich benutze diesen Datensatz: services7.arcgis.com/mOBPykOjA…dedatum&outSR=4326&f=json
    Diesen kann man übrigens auch mit anderen Parametern hier abrufen: npgeo-corona-npgeo-de.hub.arcg…eb3e0b329dd6_0/geoservice

    RodFromGermany schrieb:


    Wie sollen zwei Datensätze desselben Datums behandelt werden?

    Die Daten sollen irgendwie zusammengefasst werden, sodass ich nach dem Meldedatum auslesen kann, wieviele Elemente "AnzahlFall" enthalten sind.
    Vielleicht hilft ja der Blick auf die Daten!


    LG

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „JonathanPB“ ()

    Ich denke ich habe die Lösung für dein Problem, falls du dich aber zuerst selbst daran versuchen willst, hier mein Hinweis:
    Bereinige das Datum von Zeiteinheiten kleiner als Tage, und sammle die dann in einer List oder ähnlichem. Dann kannst du für jedes Datum die Zahlen aufaddieren.

    Lösung

    Ich hab mal aus den Daten eine Konsolenanwendung gebastelt, was dir am ende ein SortedDictionary<DateTime, int> ausgibt, mit dem du sicherlich weiterarbeiten kannst. Aus den 5000 Rohdatensätzen, werden mal ebend 219. Ich denke das resultiert daraus, dass die Daten pro Landkreis für jeden Tag gegeben sind.

    C#-Quellcode

    1. using System;
    2. using System.Collections.Generic;
    3. using System.IO;
    4. using System.Text.Json;
    5. namespace CoronaData
    6. {
    7. class Program
    8. {
    9. private static SortedDictionary<DateTime, int> _coronaData = new SortedDictionary<DateTime, int>();
    10. static void Main(string[] args)
    11. {
    12. Root temp = JsonSerializer.Deserialize<Root>(File.ReadAllText("CoronaData.json"));
    13. foreach (var item in temp.features)
    14. {
    15. DateTime date = UnixTimeStampToDateTime(item.attributes.Meldedatum);
    16. //remove all unwanted data from date. We are only interested in cases per Day.
    17. date = date.AddSeconds(-date.Second);
    18. date = date.AddMinutes(-date.Minute);
    19. date = date.AddHours(-date.Hour);
    20. if (!_coronaData.ContainsKey(date))
    21. {
    22. _coronaData[date] = item.attributes.AnzahlFall;
    23. }
    24. _coronaData[date] += item.attributes.AnzahlFall;
    25. }
    26. Console.WriteLine($"Data Count:{_coronaData.Count}");
    27. foreach (var item in _coronaData)
    28. {
    29. Console.WriteLine($"Date: {item.Key.ToShortDateString()}, Cases: {item.Value}");
    30. }
    31. Console.ReadKey();
    32. }
    33. public static DateTime UnixTimeStampToDateTime(long unixTimeStamp)
    34. => DateTimeOffset.FromUnixTimeMilliseconds(unixTimeStamp).ToLocalTime().DateTime;
    35. }
    36. public class Attributes
    37. {
    38. public int AnzahlFall { get; set; }
    39. public long Meldedatum { get; set; }
    40. }
    41. public class Feature
    42. {
    43. public Attributes attributes { get; set; }
    44. }
    45. public class Root
    46. {
    47. public List<Feature> features { get; set; }
    48. }
    49. }

    EaranMaleasi schrieb:

    Ich denke ich habe die Lösung für dein Problem
    Hmm, hmm - imo ist das Problem noch überhaupt nicht formuliert.
    Das einzige was wir haben ist:

    JonathanPB schrieb:

    Die Daten sollen irgendwie zusammengefasst werden, sodass ich nach dem Meldedatum auslesen kann, wieviele Elemente "AnzahlFall" enthalten sind.
    "irgendwie zusammenfassen" ist eigentlich nichts, was man programmieren könnte.

    Aber ich versuche mal zu formulieren, was ich denke, was der TE gemeint haben könnte:
    Die Daten sollen nach Meldedatum gruppiert werden, und je Meldedatum-Gruppe soll AnzahlFall aufsummiert werden?

    (Ist immer noch nicht 100% korrekt formuliert, aber vielleicht soweit verständlich, dass mans programmieren kann)

    Man verzeihe mir meine Klugsch...erei, aber ich versuche damit zu helfen.
    Wenn @JonathanPB es selbst versuchen will, ist das wichtigste, dass die Aufgabe, die er sich stellt, klar formuliert ist.
    Unklar formulierte Aufgaben ergeben üblicherweise noch viel unklareren Code.

    EaranMaleasi schrieb:

    Ich denke ich habe die Lösung für dein Problem


    Du lagst genau richtig, das ist die Lösung für mein Problem. Allerdings ergibt sich direkt ein neues: Ich kann mit bei bestem Willen nicht erklären, welche Werte für die Fallzahl rauskommen. Siehe Anhang.
    Vielleicht interpretiere ich den Datensatz falsch? An sich sieht der Verlauf des Graphens jedoch richtig aus...

    @ErfinderDesRades
    Entschuldige für die schwammige Formulierung; deine Problembeschreibung trifft voll zu!
    Bilder
    • graph2.png

      70,23 kB, 364×470, 61 mal angesehen

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „EaranMaleasi“ ()

    @JonathanPB Hast Du mal verfsucht aufzuklären, warum es zwei Werte gleichen Timestamps gibt?
    Ist die Summe beiderf Werte dann die Lösung?
    Wenn ja, empfehle ich, die Daten in einem SortedDictionary(Of DateTime, Long) abzulegen, da wird die Sortierung automatisch durchgeführt:
    docs.microsoft.com/de-de/dotne…ionary-2?view=netcore-3.1
    Möglicherweise genügt es dfann, dieses einem ChartControl als DataSource zuzuweisen, ich weiß aber nicht genau, ob das so geht.
    Da musst Du beim Zuweisen nur nachsehen, ob ein Wert dieses Datums bereits vorhanden iat, wenn nein: nas neue Paar anhängen, wenn ja: die Anzahl addieren.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    RodFromGermany schrieb:

    @JonathanPB Hast Du mal verfsucht aufzuklären, warum es zwei Werte gleichen Timestamps gibt?


    Ich weiß nicht ganz, was du damit meinst.
    Es gibt zwei Timestamps die angegeben werden:
    - Referenzdatum (Wann der die Person erkrankt ist)
    - Meldedatum (Wann der Fall dem RKI gemeldet wurde)

    In meinem Fall interessiert mich ja nur das Meldedatum.

    Oder meinst du, dass für ein Meldedatum mehrere Einträge vorhanden sind?
    Das ist ja genau das Problem was ich habe/hatte und wieso sich das verarbeiten so schwer gestaltet. @EaranMaleasi hat das gut erkannt:

    EaranMaleasi schrieb:


    Ich denke das resultiert daraus, dass die Daten pro Landkreis für jeden Tag gegeben sind.

    JonathanPB schrieb:

    Ich weiß nicht ganz, was du damit meinst.
    Das hier:

    JonathanPB schrieb:

    Nun ist es aber so, dass - bedingt durch den Datensatz - zwei Reports das selbe Meldedatum enthalten können.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @JonathanPB das Problem ist folgendes:
    Die API hat ein Transferlimit was durch die Eigenschaft exceededTransferLimit angegeben wird. Ich habe spaßeshalber die Daten für Ganz Deutschland für jeden Tag einzeln abgefragt, und bin Trozdem noch am 2.4.2020 in das Limit gelaufen. Meine aufkumulierten Daten beliefen sich jedoch auf 373.153 bestätigte Fälle, was bereits sehr nahe an dem ist, was bspw. Bing angibt. Zum Zeitpunkt des Postes waren das 374.740 bestätigte Fälle.

    Man müsste also, wenn exceededTransferLimit=true ist, die API nochmal abfragen, nur mit recordOffset = <anzahlErhaltenerFeatures> mit in der Query. Mehr dazu findest du in der API-Info: developers.arcgis.com/rest/ser…ature-service-layer-.htm#