der henry: js, associative arrays mit integriertem array erzeugen

Guten Morgen,

ich möchte aus verschiedenen Feldern (Input) ein assoziative array erzeugen,

Das Array sollte nach dem erstellen so aussehen. (Vorgabe)

myArray = ["name"=>"Anlage EIN", "type"=>"switch", "headline"=>"Maschine 1",
           "valuerange"=>["varname"=>"xyz", "bgcolor"=>"081500"],
                         ["varname"=>"abc", "bgcolor"=>"471100"]];

Wie kann ich das Array erzeugen?

myArray['name'] = "neuer Name";

ist klar.

Wie mache ich es aber mit dem zusätzlichen Array im Array?? Die Felder (Input) haben auch jeweils eine eindeutige "id" ("varname_0", "bgcolor_0", ""varname_1", "bgcolor_1" usw.)

Somit würde "varname_0" "xyz" überschreiben/erzeugen.

Ich hoffe ich konnte es gut erklären.

Hier habe ich schon länger rumprobiert, irgendwie sehe ich es nicht ....

Vielen Dank

der henry

  1. Hallo,

    es hat sich erledigt. Ich habe eigene Arrays erstellt und zum Schluss miteinander verbunden.

    Vielen Dank!

    1. Hallo,

      es hat sich erledigt. Ich habe eigene Arrays erstellt und zum Schluss miteinander verbunden.

      Ja. Der Weg, die „Subarrays“ zu erzeugen und in den jeweils übergeordneten Array einzuhängen, deucht mir als „einfach, logisch und ergo richtig“.

      Meine Lösung hätte übrigens so ausgesehen, dass die Variable myArray zunächst als Objekt deklariert wird (myArray={};), danach kann man dessen Eigenschaften und die Weŕte festlegen.

      myArray.valuerange wird dann als Array deklariert: myArray.valuerange=[];

      Sodann werden die einzelnen Items dieses Arrays wieder als Objekte deklariert:

      myArray.valuerange[0]={};

      und mit weiteren Eigenschaftsnamen und Werten „gefüttert”.

      Das ist „reine Bürokratie“:

      myArray={};
      myArray.name="Anlage EIN";
      myArray.type="switch";
      myArray.headline="Maschine 1";
      
      myArray.valuerange=[];
      
      myArray.valuerange[0]={};
      myArray.valuerange[0].varname="xyz";
      myArray.valuerange[0].bgcolor="081500";
      
      myArray.valuerange[1]={};
      myArray.valuerange[1].varname="abc";
      myArray.valuerange[1].bgcolor="471100";
      
      console.log(myArray)
      

      Ausgabe:

      {
        name: 'Anlage EIN',
        type: 'switch',
        headline: 'Maschine 1',
        valuerange: [
          { varname: 'xyz', bgcolor: '081500' },
          { varname: 'abc', bgcolor: '471100' }
        ]
      }
      

      Ich habe mich mal an Deine Namen gehalten. Aber, wie Felix richtig anmerkt, sind die verwirrend, weil Dein „Array“ in Javascript ein „Objekt“ ist, welches Eigenschaften mit Werten und zudem (als Wert(e) für valuerange) ein Array enthält, dessen Elemente sodann Objekte sind.(Ich habe das mal fortgeführt...)

      1. Hallo Raketenwilli,

        je nach Konstellation mag deine Formulierung sinnvoll sein, aber so, wie sie da steht, würde ich

        myArray.valuerange=[];
        
        myArray.valuerange[0]={};
        myArray.valuerange[0].varname="xyz";
        myArray.valuerange[0].bgcolor="081500";
        
        myArray.valuerange[1]={};
        myArray.valuerange[1].varname="abc";
        myArray.valuerange[1].bgcolor="471100";
        

        doch lieber als

        myArray.valuerange = [
           {
              varname: "xyz",
              bgcolor: "081500",
           },
           {
              varname: "abc",
              bgcolor: "471100",
           },
        ];
        

        schreiben. Inclusive der „überzähligen“ Kommas, die vermeiden ein vergessenes Komma bei späteren Einfügungen. Oder zumindest die Objektliterale an myarray.valuerange[0] und myarray.valuerange[1] zuweisen. Das spart eine Menge redundanter Tipp- oder Kopierarbeit.

        Rolf

        --
        sumpsi - posui - obstruxi
        1. Naja. Der Henry will ja, wenn ich seine Formulierung „ich möchte aus verschiedenen Feldern (Input) ein assoziative array erzeugen,“ richtig deute, Werte aus einem Formular einbauen. Vermutlich findet dann auch die „redundante Tipp- oder Kopierarbeit“ nicht statt, weil es eine Schleife gibt…

        2. @@Rolf B

          Inclusive der „überzähligen“ Kommas, die vermeiden ein vergessenes Komma bei späteren Einfügungen.

          Unser Codingstyle schreibt diese Kommas sogar vor. Lässt man das nach dem letzten Item bzw. Key-Value-Paar weg, meckert der Linter.

          Es ist ein Jammer, dass man diese Kommas in JSON nicht setzen darf.

          🖖 Live long and prosper

          --
          In our chants of “ICE out now”
          Our city’s heart and soul persists
          Through broken glass and bloody tears
          On the streets of Minneapolis

          — Bruce Springsteen, Streets of Minneapolis
  2. Lieber henry,

    die Idee eines assoziativen Arrays kommt aus PHP. In JavaScript verwenden wir Objekte mit passenden Eigenschaften:

    const myData = {
      "name": "Anlage EIN",
      "type": "switch",
      "headline": "Maschine 1",
      "valuerange": [
        {
          "varname": "xyz",
          "bgcolor": "081500"
        },
        {
          "varname": "abc",
          "bgcolor": "471100"
        }
      ]
    };
    

    Die Eigenschaftsnamen habe ich in doppelte Anführungszeichen gesetzt. Das hätte es hier nicht gebraucht. Aber so ist es kompatibel zum JSON-Format. Dein Server sollte die Daten am Besten gleich so senden, damit du sie mit JavaScript direkt verarbeiten kannst.

    Liebe Grüße

    Felix Riesterer

  3. Lieber henry,

    nur noch als Nachtrag, da Array-Daten in einem Formular zu erheben nicht trivial ist.

    Die Felder (Input) haben auch jeweils eine eindeutige "id" ("varname_0", "bgcolor_0", ""varname_1", "bgcolor_1" usw.)

    PHP bietet für solche Fälle an, dass man als POST-Schlüssel einen Namen mit eckigen Klammern verwendet:

    <input name="zutaten[]" type="checkbox" value="Tomaten">
    

    Das ist für die Verarbeitung mit PHP durchaus praktisch. Da PHP als Schlüssel zutaten[] sieht, wird es ein Array namens $_POST['zutaten'] anlegen und jeden so übertragenen POST-Wert als Array-Element hinzufügen:

    $_POST = [
      'zutaten' => ['Tomaten']
    ];
    

    Manchmal will man das aber explizit nicht. Vor allem dann nicht, wenn man mehrere Schlüssel-Wert-Paare für einen Datensatz haben will:

    <li>
      <input id="zutat-1" name="zutat-1" type="checkbox" value="Tomate">
      <label for="zutat-1">Tomate</label>
      <label for="menge-1">Gewicht in Gramm</label>
      <input id="menge-1" name="menge-1" type="number" min="1" max="200" value="1">
    </li>
    

    Hier hat man in den POST-Daten garantiert das Schlüssel-Wert-Paar menge-1=1, aber vielleicht keinen Schlüssel zutat-1, weil der Benutzer die Checkbox dafür nicht angehakt hat. Das soll ja bedeuten, dass die Mengenangabe für die Tomaten ohne Bedeutung ist, weil die Zutat überhaupt nicht verwendet werden soll. Stellen wir uns vor, das Formular käme mit diesen Werten an:

    $_POST = [
      'menge-1' => 1,
      'menge-2' => 40,
      'menge-3' => 1,
      'menge-4' => 1,
      'menge-5' => 7,
      'zutat-2' => 'Schinken'
      'zutat-5' => 'Salami'
    ];
    

    Hätte man hier die für PHP spezielle Array-Schreibweisen verwendet, wäre das Ergebnis dieses hier:

    $_POST['menge'] = [1, 40, 1, 1, 7];
    $_POST['zutaten'] = ['Schinken', 'Salami'];
    

    Hier hilft das Sammelarray für die Mengen überhaupt nicht, weil nicht mehr klar ist, welche Menge nun für den Schinken gilt und welche für die Salami.

    Will man nun die nummerierten Schlüssel in einer Schleife auslesen, verwendet man am besten ein reguläres Suchmuster, welches sich für das Ende des jeweiligen Schlüssels interessiert, indem es das Minuszeichen und die folgenden Ziffern haben möchte:

    $zutaten = [];
    
    foreach ($_POST as $key => $value) {
    
      // $key endet auf "-123"? $found[1] enthält dann "123"
      if (preg_match('~-(\d+)$~', $key, $found)) {
    
        $nummer = $found[1];
        $typ = preg_replace('~-\d+$~', '', $key); // entferne -123 am Ende
    
        if (!array_key_exists($nummer, $zutaten)) {
          $zutaten[$nummer] = [];
        }
    
        $zutaten[$nummer][$typ] = $value;
      }
    }
    

    Jetzt hat man die POST-Werte in einem Array, welches alle zu einer Zutat gehörenden Daten als Unter-Array enthält. Für obiges Beispiel sähe das Ergebnis so aus:

    $zutaten = [
      1 => ['menge' => 1],
      2 => ['menge' => 40, 'zutat' => 'Schinken'],
      3 => ['menge' => 1],
      4 => ['menge' => 1],
      5 => ['menge' => 5, 'zutat' => 'Salami']
    ];
    

    Somit kann man nun die empfangenen POST-Daten danach auswerten, in welchem Datensatz (Unterarray von $zutaten) es überhaupt einen Wert für zutat gibt, um den Datensatz nur dann zu akzeptieren und zu verarbeiten.

    Liebe Grüße

    Felix Riesterer

    1. Hallo Felix,

      kann man nicht auch name="zutat[0]" bzw. name="menge[0]" verwenden, auf diese Weise ein Array in $_POST["zutat"] etc erhalten und sich auf diese Weise den Tyrannosuchus Regex sparen?

      Rolf

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

        können kann man vieles. Mir ging es darum, dass man nicht unbedingt eine PHP-eigene Schreibweise verwenden muss, um das Gleiche zu erreichen.

        und sich auf diese Weise den Tyrannosuchus Regex sparen?

        Es ist mein persönlicher Spleen, dass mir der T-Rex lieber ist, als PHP-spezifische Schlüssel zu verwenden.

        Liebe Grüße

        Felix Riesterer

        1. Es ist mein persönlicher Spleen, dass mir der T-Rex lieber ist, als PHP-spezifische Schlüssel zu verwenden.

          Naja. Dann guck mal diesen Saurier:

          <!DOCTYPE html>
          <html lang="de">
            <head>
              <meta charset="utf-8">
              <title>Test</title>
            </head>
            <body>
              <form method="post" action="https://www.fastix.org/phpinfo.php#_POST">
                 <div>
          		   <input name="zutat[1][name]"    value="Salz">
          		   <input name="zutat[1][menge]"   value="1">
          		   <input name="zutat[1][einheit]" value="Teelöffel">	   
          	  </div>
                 <div>
          		   <input name="zutat[2][name]"    value="Mehl">
          		   <input name="zutat[2][menge]"   value="500">
          		   <input name="zutat[2][einheit]" value="Gramm">
          	  </div>
                 <div>
          		   <input name="zutat[3][name]"    value="Wasser">
          		   <input name="zutat[3][menge]"   value="2">
          		   <input name="zutat[3][einheit]" value="Tassen">
          	  </div>	  
                <button>senden</button>
            
              </form>
            </body>
          </html>
          

          Das oben verlinkte Beispiel zeigt, das das auch tiefer geht. 😃

          1. Die Auswertung geht dann ganz ohne Regex.

            1. Lieber Raketenwilli,

              Die Auswertung geht dann ganz ohne Regex.

              klar, kann man auch so machen. Das funktioniert mit PHP wunderbar.

              Liebe Grüße

              Felix Riesterer

              1. Felix winkte mir mit einem Zaunspfahl …

                Das funktioniert mit PHP wunderbar.

                … um mir die Richtung seines Denkens zu zeigen:

                Es ist mein persönlicher Spleen, dass mir der T-Rex lieber ist, als PHP-spezifische Schlüssel zu verwenden.

                Jein. PHP wertet den Anfrageheader aus, den der Webserver den Skripten bzw. Programmen zur Verfügung stellt (darin sind die POST-Daten) und füttert damit $_POST. Andere Sprachen machen das auch ähnlich- oder Du musst es selbst proggen oder (besser) eine fertige und hoffentlich funktionierende Bibliothek bemühen. Wenn die das Obige nicht kann, dann brauchts Du eine andere Libary - oder halt Sprache.

                1. Lieber Raketenwilli,

                  … um mir die Richtung seines Denkens zu zeigen:

                  die da lautet: In solcherlei Formularen habe ich in der Regel einen JS-Mechanismus, der mir weitere solche Felder erzeugt und dabei stur die Indices hochzählt. Da tue ich mir in der dargestellten Form leichter, als wenn ich PHP-spezifische Array-Schreibweisen erzeugen muss. - Ist ja auch praktisch, wenn beim Befüllen eines leeren Feldes einer solchen Gruppe automatisch eine neue leere Gruppe erscheint, in der man weitere Daten eintragen kann.

                  Liebe Grüße

                  Felix Riesterer

    2. Ergänzung: Habe das im Wiki an passender Stelle eingearbeitet.

      Liebe Grüße

      Felix Riesterer

      1. Mag funktionieren, deucht mir aber im Hinblick auf das eigene Hirn als „subotimal“:

        <input id="zutaten-1" name="zutaten[]" …
        

        Der Progger könnte denken, die Daten landen in $_POST['zutaten'][1]. Die stehen dann aber, wenn es das erste Input mit diesem Name ist, in $_POST['zutaten'][0].

        Für mich und mein Hirn wäre also

        <input id="zutaten-1" name="zutaten[1]" …
        

        besser.