none
Sortierte Dictionary Values addieren RRS feed

  • Frage

  • Hallo Leute,

    folgender Code erstellt mir ein sortiertes Dictionary. Meine Intention ist es, all jene Values derjenigen Keys, die doppelt(doppelt bzgl. der Keys, nicht der Values) vorhanden sind, aufzuaddieren und das Ergebnis in einer Variablen, optimal in einem neuen Dictionary zu hinterlegen. Wie stelle ich das am elegantesten an? Anmerkung: Der Key kann mittels ConvertToInt32() in ein integer konvertiert werden. Das wirft niemals eine Exception aus! Edit: Merke gerade, dass der Key eines Dictionarys unique sein muss. Könnte man sich das im Exceptionblock nicht zu nutze machen?

    Dictionary<string, double> getData = new Dictionary<string, double>(); Dictionary<string, double> newDataAfterAddition = new Dictionary<string, double>();

    double newDataAfterAddition_;

     foreach(CalculatedMissionTimeBooking booking in bookings) {

    .

    .

    getData = collectData(getData, booking.mechanicGroupNumber, booking.awIsTime);

      var items = from pair in getData
                  orderby pair.Value ascending
                   select pair;
    foreach(KeyValuePair<string, double> pair in items) {
    //wie geht's hier am elegantesten weiter?                                           
    }

    }

    private static Dictionary<string,double> collectData(Dictionary<string,double> sendDataBack, string number, double time) {
    sendDataBack.Add(number,time);
    return sendDataBack;
            }











    • Bearbeitet tklustig Mittwoch, 30. Januar 2019 13:27
    Mittwoch, 30. Januar 2019 12:29

Antworten

  • Hi,
    mit "prozedural" meine ich eine Folge von Anweisungen, die nacheinander abgearbeitet werden, ohne dass dabei Kapselungen in Klassen mit Nutzung derer Member für diesen Algorithmus in Anwendung kommen. Ein objektorientierter Ansatz könnte im Gegensatz dazu die Nutzung einer eigenen oder abgeleiteten (geerbten) Klasse sein (z.B. vom Dictionary geerbt) mit eigenen Methoden oder auch Extension für diese Klasse oder für Dictionary sein.

    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP für Developer Technologies)
    Meine Homepage mit Tipps und Tricks

    • Als Antwort markiert tklustig Donnerstag, 31. Januar 2019 08:37
    Mittwoch, 30. Januar 2019 21:00

Alle Antworten

  • Hi,
    prozedural geht das ganz einfach:

          // dic3 = dic1 + dic2
          foreach (var d1 in dic1) if (dic2.ContainsKey(d1.Key)) dic3.Add(d1.Key, d1.Value + dic2[d1.Key]);
            else dic3.Add(d1.Key, d1.Value);
          // Rest von dic2 zu dic3 hinzufügen
          foreach (var d2 in dic2) if (!dic1.ContainsKey(d2.Key)) dic3.Add(d2.Key, d2.Value);


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP für Developer Technologies)
    Meine Homepage mit Tipps und Tricks


    Mittwoch, 30. Januar 2019 13:41
  •  Merke gerade, dass der Key eines Dictionarys unique sein muss. Könnte man sich das im Exceptionblock nicht zu nutze machen?

    Hi, sehe ich auch so. eine Dictionary mit zwei gleichen Keys ist doch gar nicht möglich...

    Ich würde beim befüllen des Dictionarys abfragen, ob der Key schon vorhanden ist und dann gleich den den Value addieren. Aber das in der Exeption zu machen, ist schlechter Stil! und nicht gerade sehr performant...

    Also, so wie Peter seine Lösung!

    Gruß


    Freiberufler im Bereich Softwareentwicklung Von der PLC und Robotik zu VB.NET & C#, vorrangig WPF und UWP


    Mittwoch, 30. Januar 2019 13:50
  • Und wie bekomme ich die Werte in mein Dictionary? Sobald der key doppelt auftritt, wird die Exception 
    Ein Element mit dem gleichen Schlüssel wurde bereits hinzugefüg
    ausgelöst. Eventuell ist ein Dictionary das falsche Generikum. Welches sollte ich sonst wählen, um die Kombination Key=>value zu erfassen, ohne besagte Einschränkung?
    Mittwoch, 30. Januar 2019 13:51
  • Entweder so, wie Peter es beschrieben hast oder du bearbeitest deine Dictionary.

    Ich habe mal eine kleine Consolen-Demo erstellt.

                Dictionary<string, double> dic = new Dictionary<string, double>();
                
                for (int i = 0; i < 100; i++)
                {
                    string key = rnd.Next(1, 10).ToString();
                    double val = rnd.Next(1, 10);
    
                    if (dic.ContainsKey(key))
                    {
                        dic[key] += val;
                    }
                    else
                    {
                        dic.Add(key, val);
                    }
                }
    
                foreach (KeyValuePair<string, double> pair in dic)
                {
                    Console.WriteLine(pair.Key + "....." + pair.Value);
                }
      
                Console.WriteLine("DONE");
                Console.ReadLine();

    Es wird eine Dictionary erstellt und in einer Schleife werden 101 zufällige Keys (1-10) und Values (1-10) erstellt und entweder wird ein neues KeyValuePair erstellt oder der Wert von Value einem vorhandenen dazu addiert.

    Gruß


    Freiberufler im Bereich Softwareentwicklung Von der PLC und Robotik zu VB.NET & C#, vorrangig WPF und UWP


    Mittwoch, 30. Januar 2019 14:28
  • Hallo Peter,

    Dein Code scheint einen Syntaxfehler zu haben, zumindest in der Form, wie ich ihn aufgebröselt habe:

    /*dic1=sendDataBack dic2=getData2, dic3=getData3*/

    foreach(var d1 in sendDataBack) { if(getData2.ContainsKey(d1.Key)) { getData2.Add(d1.Key, d1.Value + getData2[sendDataBack.Key]); } else { getData3.Add(d1.Key, d1.Value); } // Rest von dic2 zu dic3 hinzufügen foreach(var d2 in getData2) { if(!sendDataBack.ContainsKey(d2.Key)) getData3.Add(d2.Key, d2.Value); } }


    +getData2[sendDastaBack.Key] geht nicht!


    Fehler	2	1-Argument: Kann nicht von "System.Collections.Generic.Dictionary<string,double>.KeyCollection" in "string" konvertiert werden.	D:\SVN\C#\TimeTrackingApp\TimeTrackingApp\Program.cs	541	65	TimeTrackingApp
    
    
    Fehler	1	Die beste Übereinstimmung für die überladene System.Collections.Generic.Dictionary<string,double>.this[string]-Methode hat einige ungültige Argumente.	D:\SVN\C#\TimeTrackingApp\TimeTrackingApp\Program.cs	541	56	TimeTrackingApp
    


    • Bearbeitet tklustig Mittwoch, 30. Januar 2019 15:03
    Mittwoch, 30. Januar 2019 14:52
  • Das soll wohl getData2.Add(d1.Key, d1.Value + getData2[sendDataBack.Value]); sein.

    Ist aber so schwer nicht zu erraten...

    Gruß


    Freiberufler im Bereich Softwareentwicklung Von der PLC und Robotik zu VB.NET & C#, vorrangig WPF und UWP

    Mittwoch, 30. Januar 2019 15:10
  • Korrekt. Klappt aber trotzdem nicht. der Algorithmus versagt, zumindest in folgender Form. es besteht immer wieder das Problem, das Keys eingefügt werden, die bereits exisitieren:

            private static Dictionary<string, double> collectData(Dictionary<string, double> sendDataBack, string number, double time) {
                string key = String.Empty; ;
                foreach(KeyValuePair<string, double> kvp in sendDataBack) {
                    key = kvp.Key;
                }
                if(!sendDataBack.ContainsKey(key)) {
                    sendDataBack.Add(number, time);
                } else {
                    // dic3 = dic1 + dic2
                    foreach(var d1 in sendDataBack) {
                        if(getData2.ContainsKey(d1.Key)) {
                            getData2.Add(d1.Key, d1.Value + getData2[d1.Key]);
                        } else { //hier wird versucht, key mehrfach einzufügen
                            getData3.Add(d1.Key, d1.Value);
                        }
                        // Rest von dic2 zu dic3 hinzufügen
                        foreach(var d2 in getData2) {
                            if(!sendDataBack.ContainsKey(d2.Key))
                                getData3.Add(d2.Key, d2.Value);
                        }
                    }
                }
                return sendDataBack;
            }



    • Bearbeitet tklustig Mittwoch, 30. Januar 2019 15:16
    Mittwoch, 30. Januar 2019 15:13
  • Du fragst, ob in "getData2" ein bestimmter Key vorhanden ist und versuchst dann in "getData3" einen Key hinzuzufügen....

    Das ist alles, aber bestimmt nicht sicher!

    Zumal niemand weiß, was in "getData2" und "getData3" drinsteckt oder woher das kommt.

    Für mich persönlich ist das eh ein schlechter Stil, in einer Funktion oder Methode mit Eingagsparametern und einem Rückgabewert private oder öffentliche Eigenschaften/Variablen zu verwenden..

    Und was soll das überhaupt sein? Das macht ja gar keinen Sinn:

                string key = String.Empty; ;
                foreach (KeyValuePair<string, double> kvp in sendDataBack)
                {
                    key = kvp.Key;
                }
                if (!sendDataBack.ContainsKey(key))...

    So bekommst doch immer nur den letzten Key aus sendDataBack...

    Ok, wenn man das zweimal liest, muss man die Hände über den Kopf zusammenschlagen... Nicht böse gemeint ;)

    Aber das was du hier postest, kann nur der Entwurf vom Entwurf einer Idee sein... Eigentlich macht da nichts Sinn..

    Gruß


    Freiberufler im Bereich Softwareentwicklung Von der PLC und Robotik zu VB.NET & C#, vorrangig WPF und UWP




    Mittwoch, 30. Januar 2019 15:24
  • Nun ja, das ist halt die Interpretation von dem, was Peter als "prozeduralen" Lösungsansatz gepostet hatte. Was immer er mit "prozedural" meinte (C# ist doch durch und durch objektorientiert,oder?). Ich werde das Dictionary jetzt verwerfen und anstatt dessen das Generika

    List<Tuple<string, int>> liste = new List<Tuple<string, int>>();

    liste.Add(new Tuple<int, string>(integer, string));


    verwenden. Den Algorithmus, der mir bei Stringleichheit die dazugehörigen Integerwerte aufaddiert muss ich mir dann halt selber schreiben. So long...




    • Bearbeitet tklustig Mittwoch, 30. Januar 2019 19:20
    Mittwoch, 30. Januar 2019 19:18
  • Hi,
    mit "prozedural" meine ich eine Folge von Anweisungen, die nacheinander abgearbeitet werden, ohne dass dabei Kapselungen in Klassen mit Nutzung derer Member für diesen Algorithmus in Anwendung kommen. Ein objektorientierter Ansatz könnte im Gegensatz dazu die Nutzung einer eigenen oder abgeleiteten (geerbten) Klasse sein (z.B. vom Dictionary geerbt) mit eigenen Methoden oder auch Extension für diese Klasse oder für Dictionary sein.

    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP für Developer Technologies)
    Meine Homepage mit Tipps und Tricks

    • Als Antwort markiert tklustig Donnerstag, 31. Januar 2019 08:37
    Mittwoch, 30. Januar 2019 21:00