der henry: mein erstes node object

Hallo,

ich möchte ein object erstellen

So sollte es aussehen ...

datenpunktliste.plcname.plcvarname
datenpunktliste.plcname.type
datenpunktliste.plcname.db

Als Beispiel lese ich aus einem Object mit Namen "zeile"

Ich komme aber mit der Verschachtelung/Klammern nicht zurecht .. mein Ansatz ...

Object.assign(datenpunktliste, {"plcname": act_plcname};

// hier käme dann eine Schleife ....

  Object.assign(datenpunktliste, {"spsname":
                    [
                         {
                            "plcvarname": zeile.spsvarname,
                                  "type": zeile.datentyp,
                                    "db": zeile.db
                         }
                    ]};

Der Zugriff wäre dann ??

let mytype = datenpunktliste.M1.type;

Vielen Dank

greenhorn

  1. Hallo Henry,

    ich kann Dir nur ansatzweise folgen. Mir scheint, mit plcname meinst Du einen beliebigen Schlüsselbegriff, wie z.B. "M1".

    Diese Anweisung

    Object.assign(datenpunktliste, {"plcname": act_plcname});
    

    erzeugt aber in datenpunktliste lediglich eine Eigenschaft namens plcname und speichert darin den Wert von act_plcname. Genausogut könntest Du

    datenpunktliste.plcname = act_plcname;
    

    schreiben. Object.assign kopiert einfach die enumerierbaren Eigenschaften eines Objekts in ein anderes.

    Wenn Du eine Eigenschaft erzeugen möchtest, deren Name in act_plcname steht, musst Du die Notation mit eckigen Klammern verwenden:

    datenpunktliste[act_plcname] = ...;
    

    Und in Datenpunktliste möchtest Du unter unterschiedlichen Schlüsseln (also act_plcname-Werte) dann Informationsobjekte zu diesem plcname hinterlegen? Wie kommst Du im Schleifendurchlauf an diese Werte heran? Das zeigt dein Code nicht.

    Und eventuell ist ein Objekt auch gar nicht die richtige Lösung für Dich. Die Datenstruktur, die Du hier zu planen scheinst, ist eine Map. Und dafür gibt's in JavaScript die Map-Klasse. Der Wiki-Artikel steigt etwas abstrakt ein, lies einfach, er enthält einige Beispiele.

    datenstrukturliste = new Map();
    datenstrukturliste.set(act_plcname, { plcvarname: zeile.spsvarname,
                                      type: zeile.datentyp,
                                        db: zeile.db });
    
    plcdaten = datenstrukturliste.get("M1");
    
    alleKeys = Array.from(datenstrukturliste.keys());
    

    Früher gab es diese Klasse nicht und man hat Objekte als Maps missbraucht. Aber Node.js sollte Maps kennen.

    Rolf

    --
    sumpsi - posui - obstruxi
    1. Hallo Rolf,

      ich möchte meine Daten nochmals, aber detaillierter erklären.

      Ich hole mir die Daten aus einer mysql Datenbank. Hier bekomme ich ein Array mit Objekten zurück.

      Um im laufendem Programm gezielter und einfacher auf die Daten zugreifen zu können, ohne jeweils eine Schleife benützen zu müssen, möchte ich die Daten "anders" abspeichern bzw. einmalig umkopieren.

      Maschinenname: M1 
                        plcvarname: Drehzahl 
                                        format: double
                                        offset: 120   
                                        .. usw  
       
                        plcvarname: Temperatur 
                                        format: double
                                        offset: 128   
                                        .. usw  
      
                               usw.
      
      Maschinenname: M2
      
                        plcvarname: Drehzahl 
                                        format: double
                                        offset: 220   
                                        .. usw  
       
                        plcvarname: Temperatur 
                                        format: double
                                        offset: 228   
                                        .. usw  
      
                               usw.
      

      Alle Daten in einem "Speicher"

      Daher dachte ich an ein verschalteltes object

      Lesen der Daten z.B. ... (eventuell klammern bzw. anders formatieren)

      let x = datenpunktliste.M1.Drehzahl.format
      

      oder

      let y = datenpunktliste.M2.Drehzahl.offeset
      

      Eventuell liege ich falsch und so etwas geht gar nicht 😉 Bin für jeden Tip dankbar !!

      Gruß

      1. Moin Henry,

        ich habe in Deiner Antwort den Code entsprechend ausgezeichnet, damit er lesbarer ist. Das kannst Du ab jetzt dann auch selbst 😉

        Viele Grüße
        Robert

      2. Moin Henry,

        Maschinenname: M1 
                          plcvarname: Drehzahl 
                                          format: double
                                          offset: 120   
                                          .. usw  
         
                          plcvarname: Temperatur 
                                          format: double
                                          offset: 128   
                                          .. usw  
        
                                 usw.
        
        Maschinenname: M2
        
                          plcvarname: Drehzahl 
                                          format: double
                                          offset: 220   
                                          .. usw  
         
                          plcvarname: Temperatur 
                                          format: double
                                          offset: 228   
                                          .. usw  
        
                                 usw.
        

        Lesen der Daten z.B. ... (eventuell klammern bzw. anders formatieren)

        let x = datenpunktliste.M1.Drehzahl.format
        

        oder

        let y = datenpunktliste.M2.Drehzahl.offeset
        

        das entsprechende Objekt sähe in etwa so aus:

        const datenpunktliste = {
            M1: {
                Drehzahl: {
                    format: 'double',
                    offset: 120,
                    // …
                },
                Temperatur: {
                    format: 'double',
                    offset: 128,
                    // …
                }
            },
            M2: {
                Drehzahl: {
                    format: 'double',
                    offset: 220,
                    // …
                },
                Temperatur: {
                    format: 'double',
                    offset: 228,
                    // …
                }
            }
        };
        

        Offensichtlich sind M1 und M2 vom gleichen Objekt-Typ („Maschine“) und beinhalten die gleichen Objekttypen (physikalische Einheiten), d.h. es sind Abkürzungen möglich:

        function Einheit(format, offset, /* … */) {
            this.format = format;
            this.offset = offset;
            // …
        }
        
        function Maschine(drehzahl, temperatur, /* … */) {
            this.Drehzahl = new Einheit('double', drehzahl, /* … */);
            this.Temperatur = new Einheit('double', temperatur, /* … */);
        }
        
        const datenpunktliste = {
            M1: new Maschine(120, 128, /* … */),
            M2: new Maschine(220, 228, /* … */)
        }
        

        Viele Grüße
        Robert

        1. Hallo Robert,

          vielen Dank für deine Unterstützung.

          Du gibst in deinem Beispiel den plcvarnamen fest vor. Das ist aber nicht so, dieser kann unterschiedlich sein, deshalb habe ich den key "plcvarnamen" benutzt. Auch das format z.B. ist nicht immer "double"

          Maschinenname: M1 
                            plcvarname: Drehzahl 
                                            format: double
                                            offset: 120   
                                            .. usw  
           
                            plcvarname: Temperatur 
                                            format: double
                                            offset: 128   
                                            .. usw  
          
          

          Es müsste so aussehen ... Klammer und Komma -Setzung eventuel falsch

          const datenpunktliste = {
                      maschinenname: M1 {
                              plcvarname:   Drehzahl {
                                                format: 'double',
                                                offset: 120,
                                                     },
          
                              plcvarname: Temperatur {
                                                format: 'integer',
                                                offset: 128,
                                                     },
          
                              plcvarname: Oeffnung   {
                                                format: 'dword',
                                                offset: 132,
                                                     }
                      
                                        },
          
                      maschinenname: M2 {
                              plcvarname:   Drehzahl {
                                                format: 'double',
                                                offset: 220,
                                                     },
          
                              plcvarname:     Temp_1 {
                                                format: 'integer',
                                                offset: 228,
                                                     },
          
                              plcvarname:     Temp_2 {
                                                format: 'dword',
                                                offset: 232,
                                                     }
                                        },
          };
          

          PS: Die einzelnen Maschinen (Maschinenname) können die gleichen "plcvarnamen" haben, müssen aber nicht.

          Wie kann ich diese Struktur mittels Programm erzeugen ... man gehe von einem leeren objekt, in diesem Fall "datenpunktliste" aus ?

          Vielen Dank

          1. Hallo Henry,

            das kommt davon, wenn man sein Problem nicht anständig beschreibt, sondern davon ausgeht, dass fremde Menschen die eigene Problemdomäne eh kennen. Die Leute machen dann irgendwelche Annahmen und liegen automatisch falsch. Deshalb auch meine Rückfrage von 11:06 Uhr.

            Wir brauchen eine exakte Beschreibung der Eingabedaten und eine exakte Vorgabe, wie die Ausgabe aussehen soll. Andernfalls raten wir nur rum.

            Es müsste so aussehen ... Klammer und Komma -Setzung eventuel falsch...

            Nicht nur die. Das ist kein JavaScript, sondern Phantasiesyntax. Wie es Javascript-mäßiger aussehen könnte, zeige ich gleich. Der erläuternde Wiki-Artikel ist Objekte und ihre Eigenschaften.

            Ich versuche mal einen Schritt in eine möglicherweise richtige Richtung. Deine Eingabedaten sind ein Array aus Objekten mit den Schlüsseln Maschinenname, plcvarname, format, offset und noch ein paar mehr? Mit Array- und Objektliteralen in JavaScript könnte man das so aufschreiben:

            eingabe = [
               { Maschinenname: "M1", plcvarname: "Drehzahl", format: "double", offset: 220, dings: 17, bums: 99 },
               { Maschinenname: "M1", plcvarname: "Temperatur", format: "integer", offset: 128, dings: 11, bums: 77 },
               { Maschinenname: "M1", plcvarname: "Oeffnung", format: "dword", offset: 132, dings: 13, bums: 47 },
               { Maschinenname: "M2", plcvarname: "Drehzahl", format: "double", offset: 220, dings: 17, bums: 99 },
               { Maschinenname: "M2", plcvarname: "Temp_1", format: "integer", offset: 128, dings: 11, bums: 77 },
               { Maschinenname: "M2", plcvarname: "Temp_2", format: "integer", offset: 132, dings: 13, bums: 47 }
            ];
            

            Soweit richtig geraten?

            Entstehen soll daraus ein Objekt, das als Literal geschrieben so aussähe?

            datenpunktliste = {
               M1: { 
                  Drehzahl: { format: "integer", offset: 220, dings: 17, bums: 99 },
                  Temperatur: { format: "integer", offset: 128, dings: 11, bums: 77 },
                  Oeffnung: { format: "dword", offset: 132, dings: 13, bums: 47 },
               },
               M2: {
                  Drehzahl: { format: "integer", offset: 220, dings: 17, bums: 99 },
                  Temp_1: { format: "integer", offset: 128, dings: 11, bums: 77 },
                  Temp_2: { format: "integer", offset: 132, dings: 13, bums: 47 },
               },
            };
            

            Ist das richtig?

            Die Eigenschaftsnamen "M1", "M2", "Drehzahl", "Temperatur" und so weiter sind dabei ein Risiko. Wenn deine DB-Abfrage einen Maschinennamen wie "Nummer 5" oder "NGC-1701" liefert, ist das KEIN gültiger Name. Objekteigenschaften mit solchen Namen sind zwar zulässig, sind aber nicht über die Punkt-Schreibweise erreichbar. In einem Objektliteral müssen sie dann in Anführungszeichen stehen, und beim Zugriff auf die Eigenschaft brauchst Du die Index-Notation. Steht alles im Abschnitt "Eigenschaften mit irregulären Namen" im verlinkten Wiki-Artikel.

            Beim Erstellen von Eigenschaften mit variablen Namen brauchst Du eh die Index-Notation.

            Rolf

            --
            sumpsi - posui - obstruxi
            1. Hallo,

              eingabe = [
                 { Maschinenname: "M1", plcvarname: "Drehzahl", format: "double", offset: 220, dings: 17, bums: 99 },
                 { Maschinenname: "M1", plcvarname: "Temperatur", format: "integer", offset: 128, dings: 11, bums: 77 },
                 { Maschinenname: "M1", plcvarname: "Oeffnung", format: "dword", offset: 132, dings: 13, bums: 47 },
                 { Maschinenname: "M2", plcvarname: "Drehzahl", format: "double", offset: 220, dings: 17, bums: 99 },
                 { Maschinenname: "M2", plcvarname: "Temp_1", format: "integer", offset: 128, dings: 11, bums: 77 },
                 { Maschinenname: "M2", plcvarname: "Temp_2", format: "integer", offset: 132, dings: 13, bums: 47 }
              ];
              

              Soweit richtig geraten?

              Ja, das ist richtig

              datenpunktliste = {
                 M1: { 
                    Drehzahl: { format: "integer", offset: 220, dings: 17, bums: 99 },
                    Temperatur: { format: "integer", offset: 128, dings: 11, bums: 77 },
                    Oeffnung: { format: "dword", offset: 132, dings: 13, bums: 47 },
                 },
                 M2: {
                    Drehzahl: { format: "integer", offset: 220, dings: 17, bums: 99 },
                    Temp_1: { format: "integer", offset: 128, dings: 11, bums: 77 },
                    Temp_2: { format: "integer", offset: 132, dings: 13, bums: 47 },
                 },
              };
              

              Ist das richtig?

              Ja richtig, damit kann ich gut leben !! Ich möchte jetzt in einer Schleife das Objekt füllen. Dazu habe ich nachfolgenden Code

              result.forEach(function (zeile) {
                            sps_datenpunktliste = {
                                    [aktiver_spsname]: {
                                          [zeile.spsvarname]: {
                                                 datentyp: zeile.datentyp, db: zeile.db, offset: zeile.offset, bit: zeile.bit, format: zeile.format, nachkomma: zeile.nachkomma
                                          }
                                     }
                             }
              });
              

              Dies funktioniert in so weit, das jede Zeile im Objekt überschrieben wird, was ich auch verstehe, da das Objekt komplett neu beschrieben wird.

              Trotz intensiver suche im Netz habe ich nichts passendes zum Thema "dynamische beschreiben verschachtelter Objekte" gefunden. 😉

              Mein Ansatz wäre nun gewesen

              result.forEach(function (zeile) {
                         sps_datenpunktliste = aktiver_spsname;
                         sps_datenpunktliste[aktiver_spsname] = zeile.spsvarname;
              
                         sps_datenpunktliste[aktiver_spsname][zeile.spsvarname] = {
                                                                              datentyp: zeile.datentyp, db: zeile.db, offset: zeile.offset, bit: zeile.bit, format: zeile.format, nachkomma: zeile.nachkomma }
                              });
              

              Ich kann den Key "aktiver_spsname" beschreiben ... soweit funktioniert es. Dann müsste ich eigentlich eine Stufe tiefer kommen und "zeile.spsvarname" beschreiben können ... Pustekuchen ...

              Hier komm ich nicht weiter ...

              1. Moin Henry,

                Ich möchte jetzt in einer Schleife das Objekt füllen. Dazu habe ich nachfolgenden Code

                result.forEach(function (zeile) {
                    sps_datenpunktliste = {
                        [aktiver_spsname]: {
                            [zeile.spsvarname]: {
                                datentyp: zeile.datentyp,
                                db: zeile.db,
                                offset: zeile.offset,
                                bit: zeile.bit,
                                format: zeile.format,
                                nachkomma: zeile.nachkomma
                            }
                        }
                    }
                });
                

                Vielleicht möchtest Du dich noch einmal genauer mit der JavaScript-Syntax auseinandersetzen. Wir haben ein ganzes Wiki dazu. Kurz beschrieben macht Dein Code folgendes:

                In jedem Schleifendurchlauf wird ein Objekt sps_datenpunktliste angelegt, das seine Attributnamen aus den Variablen aktiver_spsname und zeile.spsvarname nimmt. Erstere Variable scheint dabei global und konstant für jede Zeile zu sein.

                Dies funktioniert in so weit, das jede Zeile im Objekt überschrieben wird, was ich auch verstehe, da das Objekt komplett neu beschrieben wird.

                Trotz intensiver suche im Netz habe ich nichts passendes zum Thema "dynamische beschreiben verschachtelter Objekte" gefunden. 😉

                Vielleicht liegt es daran, dass Dein Suchbegriff kein Fachbegriff (in JavaScript) ist und nicht im Entferntesten beschreibt, was Du vermutlich eigentlich tun möchtest: Objekte um Eigenschaften erweitern. Es ist ja nicht so, als hätte das Rolf bereits in seiner ersten Antwort beschrieben

                Mein Ansatz wäre nun gewesen

                result.forEach(function (zeile) {
                    sps_datenpunktliste = aktiver_spsname;
                    sps_datenpunktliste[aktiver_spsname] = zeile.spsvarname;
                
                    sps_datenpunktliste[aktiver_spsname][zeile.spsvarname] = {
                        datentyp: zeile.datentyp,
                        db: zeile.db,
                        offset: zeile.offset,
                        bit: zeile.bit,
                        format: zeile.format,
                        nachkomma: zeile.nachkomma
                    }
                });
                

                Ich kann den Key "aktiver_spsname" beschreiben ... soweit funktioniert es. Dann müsste ich eigentlich eine Stufe tiefer kommen und "zeile.spsvarname" beschreiben können ... Pustekuchen ...

                Dein Code macht folgendes:

                1. Lege das Objekt sps_datenpunktliste neu als String an.
                2. Erweitere den String um das Attribut mit dem Namen, der in aktiver_spsname steht und weise diesem den String aus zeile.spsvarname zu.
                3. Erweitere diesen String um das Attribut mit dem Namen aus zeile.spsvarname und weise diesem ein neues Objekt zu.

                Ich könnte mir vorstellen, dass das Weglassen der ersten beiden Code-Zeilen in der Schleife und entsprechend korrektes Initialisieren von sps_datenpunktliste bereits ausreicht um dort hin zu kommen, wo Du eigentlich hinmöchtest.

                Viele Grüße
                Robert

                1. Hallo Robert,

                  1. Lege das Objekt sps_datenpunktliste neu als String an.
                  2. Erweitere den String um das Attribut mit dem Namen, der in aktiver_spsname steht und weise diesem den String aus zeile.spsvarname zu.

                  Das ist eine beliebte Falle, in die man bei JavaScript tappen kann. Ein String ist ein primitiver Typ, kein Objekt.

                  let a = "Hallo";
                  console.log(typeof a);
                  // "string"
                  

                  Da müsste "object" stehen, wenn a ein Objekt wäre. Verwendet man einen primitiven Typ wie ein Objekt, findet etwas statt, was in anderen Sprachen "boxing" genannt wird: der primitive Wert wird in ein Objekt eingekapselt. In diesem Fall: String (großes s). Auf diesem Objekt wird die objektorientierte Aktion ausgeführt, danach wird das Objekt wieder entfernt.

                  Dieser Code

                  let a = "Hallo";
                  a.who = "Welt";
                  console.log(a.who);
                  

                  weist dem String "Hallo" keine Eigenschaft who zu. Das wäre fatal, weil Strings unveränderlich sind und von der JS Engine internalisiert werden (heißt: Steht dreimal "Hallo" im Code, gibt's diesen String tatsächlich nur einmal. Würde man ihm Eigenschaften zuweisen können, würde sich diese Änderung auf jede Stelle auswirken, wo "Hallo" irgendwohin zugewiesen wird).

                  Was in Wahrheit passiert, ist:

                  let a = "Hallo";
                  const __tempString = new String(a);
                  __tempString.who = "Welt";
                  console.log(a.who);   // undefined
                  

                  Und ja, das passiert auch beim Anwenden von Stringmethoden!

                  let a = "Hallo";
                  console.log(a.substring(0,1) + a.substring(4,5)); // "Ho"
                  

                  ist in Wahrheit

                  let a = "Hallo";
                  const __tempString1 = new String(a);
                  const __tempResult1 = __tempString1.substring(0,1);
                  const __tempString2 = new String(a);
                  const __tempResult2 = __tempString2.substring(4,5);
                  console.log(__tempResult1 + __tempResult2);
                  

                  Wobei eine ordentliche JS-Engine erkennen sollte, dass sie hier mit einem Temp-String auskommt. Andererseits kann so eine Optimierung auch gefährlich enden, die Engine muss also SEHR gut sein, um Fälle wie diesen hier richtig zu behandeln:

                  // Nicht nachmachen!
                  let a = "Hallo";
                  
                  function setA(val) {
                     a = val;
                     return "*";
                  }
                  
                  console.log(a.substring(0,1)+setA("Wonka")+a.substring(4,5));
                  

                  Welches Ergebnis würdest Du erwarten? "H*o" oder "H*a"?

                  Rolf

                  --
                  sumpsi - posui - obstruxi
      3. Hallo Henry,

        sicher geht das. Du hast es aber wieder geschafft, mich zu verwirren.

        Dein "Array"-Beispiel ist hierarchisch dargestellt. Ist das bei Dir so? Wenn ja, dann schreib es doch bitte als Objektliteral auf, damit man die Struktur richtig erkennt.

        Oder ist das Array flach, und die Spalten für Maschinenname und plcvarname wiederholen sich für jedes Datenelement? So, wie es mysqli in PHP als Resultset liefert? Wie heißen die Spalten exakt?

        Rolf

        --
        sumpsi - posui - obstruxi