Tobi: letztes Komma streichen

Hallo,

ich habe das schon (gefühlte) 1000 mal gelöst, aber bin nicht sicher, ob es da nicht einen einfacheren Weg gibt:

  
foreach ($array_test AS $Einzel) {  
$aufzaehlung .= $Einzel.",";  
}  

Das bedeutet ja, daß ich am Ende der Aufzählung 1 Komma zuviel habe, weshalb ich eine weitere for Schleife einbaue, die mir das Komma wegläßt, falls $Einzel das letzte Element des Arrays war.

Gibt es dazu eine schlankere Lösung?

Tobi

  1. Tach!

    foreach ($array_test AS $Einzel) {
    $aufzaehlung .= $Einzel.",";
    }

    
    > Gibt es dazu eine schlankere Lösung?  
      
    [implode()](http://www.php.net/manual/en/function.implode.php)  
      
      
    dedlfix.
    
    1. implode()

      Ja, genau sowas meinte ich.
      Und wie würde ich implode dann einsetzen, wenn ich sowas hier schlanker machen will?

        
      $i=0;  
      foreach ($array_test AS $Einzel) {  
      $i++;  
      $aufzaehlung .= "".$Einzel."-".$weitere_variable."-".$und_noch_eine;  
      while ($i < count($array_test)) {  
      $aufzaehlung .= ",";  
      }  
      }  
      
      

      So?

        
      foreach ($array_test AS $Einzel) {  
      $array_test[] = "".$Einzel."-".$weitere_variable."-".$und_noch_eine;  
      $aufzaehlung = implode(",", $array_test);  
      }  
      
      

      Tobi

      1. foreach ($array_test AS $Einzel) {
        $array_test[] = "".$Einzel."-".$weitere_variable."-".$und_noch_eine;
        $aufzaehlung = implode(",", $array_test);
        }

          
        Damit wiederholst du immer alle Elemente für jedes Element, das du hinzufügst.  
          
        `implode()`{:.language-php} kann nur was mit "fertigen" Arrays anfangen. Du könntest dir aber eine Funktion dazu schreiben wie zB.  
          
        ~~~php
          
        function extendedImplode($array, $prefix, $suffix, $delimiter) {  
            return $prefix.implode($delimiter, $suffix.$delemiter.$prefix).$suffix;  
        }
        

        Aufrufen würdest du dann für obiges Beispiel:
        $aufzaehlung = extendedImplode($array_test,"","-$weitere_variable-$und_noch_eine",",");

        MfG
        bubble

        --
        If "god" had intended us to drink beer, he would have given us stomachs. - David Daye
      2. Tach!

        implode()
        Ja, genau sowas meinte ich.
        Und wie würde ich implode dann einsetzen, wenn ich sowas hier schlanker machen will?

        $i=0;
        foreach ($array_test AS $Einzel) {
        $i++;
        $aufzaehlung .= "".$Einzel."-".$weitere_variable."-".$und_noch_eine;
        while ($i < count($array_test)) {
        $aufzaehlung .= ",";
        }
        }

          
        Die while-Schleife in dem foreach ist falsch. Sie führt zu einer Endlosschleife. Das Hinzufügen eines Leerstrings in einer Stringverknüpfung ist nich sinnvoll. Es sei denn, du willst einen impliziten Typecast provizieren:  
          
        $foo = "" . 42;  
          
        Der lässt sich aber intuitiver als expliziter Typecast schreiben  
          
        $foo = (string)42;  
          
        Aber zur eigentlichen Frage. Die beiden Werte $weitere\_variable $und\_noch\_eine sowie die Bindestriche sind innerhalb der Schleife feststehende Werte, die vor oder nach dem Komma zu stehen kommen. Du kannst also den Komma\_String im implode() um diese Werte erweitern.  
          
        Oftmals will man eine Liste von Werten in Hochkommas oder Anführungszeichen einrahmen und sie durch Komma oder dergleichen trennen. Also  
          
        "foo", "bar", "qux"  
          
        erzeugen. Dann kann als $glue im implode() ein '", "' genommen, sowie vorn und hinten dran das erste und letzte " angehängt werden. Aber Achtung! Wenn man einen Kontextwechsel zu beachten hat, geht das so einfach nicht. Man kann jedoch immerhin das implode für die Kommas verwenden und das Quotieren und Kontextwechsel-Behandeln in einer vorhergehenden foreach-Schleife abwickeln.  
          
          
        dedlfix.
        
  2. Gibt es dazu eine schlankere Lösung?

    Ja

    foreach ($array_test AS $Einzel) {
       $aufzaehlung .= $Einzel.",";
    }
    $aufzaehlung = substr( $aufzaehlung, 0, -1);

      
    Selbst wenn du php interne funktionen verwendest werden die intern wahrscheinlich auch ein foreach benutzen. Deshalb benutze ich für sowas immer rudimentäres php mit dem substr am ende. Somit hab ich die genaue kontrolle was passieren soll. MEistens bläht man solche Sachen dann doch noch auf. Dann kommen noch inhalte von anderen Arrays dazu etc...  
      
    Gruß  
    echo substr( "T-Rex ist voll clever", 0, -7);
    
    1. gudn tach!

      Selbst wenn du php interne funktionen verwendest werden die intern wahrscheinlich auch ein foreach benutzen.

      die internen funktionen werden aber hoffentlich wesentlich schneller in der ausfuehrung sein.

      Deshalb benutze ich für sowas immer rudimentäres php mit dem substr am ende. Somit hab ich die genaue kontrolle was passieren soll.

      das ist allerdings ansichtssache.
      php ist zwar dafuer bekannt, fuer jeden kleinen furz eine eigene funktion zu besitzen, was beim programmieren zugegeben wenig spass macht, siehe auch http://tnx.nl/php.html#chaos. aber wenn man mit vielen selbstgebastelten funktionalitaeten etwas bastelt, was es eigentlich schon vorgefertigt gibt, dann hat des normalerweise gleiche mehrere nachteile:
      * die uebersichtlichkeit und verstaendlichkeit ist bei einer zeile "join" bzw. "implode" besser als bei mehrzeiligem "foreach ..."
      * aufgrund der uebersichtlichkeit ist sowas auch weniger fehleranfaellig und besser wartbar, zumal man selbst _immer_ mehr fehler macht als die leute, die programmiersprachen erstellen.
      * die ausfuehrgeschwindigkeit ist bei internen funktionen fast nie langsamer; haeufig aber schneller als selbstgebasteltes.

      MEistens bläht man solche Sachen dann doch noch auf. Dann kommen noch inhalte von anderen Arrays dazu etc...

      erst wenn die bordmittel nicht ausreichen, sollte man selbst was basteln, imho.

      prost
      seth

      1. Selbst wenn du php interne funktionen verwendest werden die intern wahrscheinlich auch ein foreach benutzen.
        die internen funktionen werden aber hoffentlich wesentlich schneller in der ausfuehrung sein.

        Yep, und im Falle von implode() vs foreach auch noch sehr viel schneller:

        function t1($arr) {  
            $str = "";  
            foreach($arr as $element)  
                $str .= "$element,";  
            return substr($str,0,-1);  
        }  
        function t2($arr) {  
            return implode(",",$arr);  
        }  
        $arr = Array();  
        for($i=0; $i<1000; $i++)  
            $arr[] = (string)$i;  
        $t = microtime(true); for($i=0; $i<100000; $i++) t1($arr); var_dump(microtime(true)-$t);  
        // float(27.302348852158)  
        $t = microtime(true); for($i=0; $i<100000; $i++) t2($arr); var_dump(microtime(true)-$t);  
        // float(3.3718700408936)  
        
        

        Meine Vermuting ist, dass bei implode() intern die resultierende String-Menge zuerst ermittelt wird und dann ein Speicher der Größe reserviert wird, sodass dann nur noch die Daten hineinkopiert werden müssen.

        Bei der foreach-Variante allerdings wächst der String immer weiter und dadurch muss dann wohl auch mal der gesamte Speicherbereich an eine andere Stelle umziehen und wird somit öfters umkopiert.

        MfG
        bubble

        --
        If "god" had intended us to drink beer, he would have given us stomachs. - David Daye
        1. Meine Vermuting ist, dass bei implode() intern die resultierende String-Menge zuerst ermittelt wird und dann ein Speicher der Größe reserviert wird, sodass dann nur noch die Daten hineinkopiert werden müssen.

          Wenn ich den Quellcode richtig interpretiere, dann liegt meine Vermutung doch falsch.

          MfG
          bubble

          --
          If "god" had intended us to drink beer, he would have given us stomachs. - David Daye
          1. Tach!

            Meine Vermuting ist, dass bei implode() intern die resultierende String-Menge zuerst ermittelt wird und dann ein Speicher der Größe reserviert wird, sodass dann nur noch die Daten hineinkopiert werden müssen.
            Wenn ich den Quellcode richtig interpretiere, dann liegt meine Vermutung doch falsch.

            Ja, und zwar weil in einem PHP-Array Werte aller möglichen Typen enthalten sein können. Diese hätten in einem ersten Schritt gegebenenfalls zu String konvertiert und irgendwo zwischengespeichert werden müssen.

            Um einen Teil von seths Ausführungen auf den Punkt zu bringen: Code breaks your application. Dieser Merksatz ist so schön widersprüchlich. Man braucht doch Code für die Anwendung, wieso ist er nicht nur ihr Baumaterial sondern auch ihr Verhängnis? Eben weil mehr Code mehr potentielle Fehlerquellen und/oder Ansatzpunkte für nachträglich "eingeänderte" Fehler enthält.

            Übrigens: Die Messanordnung mit einer for-Schleife mit sehr hoher Wiederholungsanzahl kann zwar generell einen Laufzeitunterschied aufzeigen, aber praxisrelevant sind die entstehenden Zahlen nicht. Besser wäre, zwei Geradeaus-Scripte zu erstellen und dann mit einem Tool wie ab (= Apache-Benchmark) ermitteln, wieviele Requests pro Zeiteinheit abgearbeitet werden können. Dabei sollte man sich nicht auf den ersten Durchlauf verlassen. Weitere können durchaus schneller werden, weil dann bereits Cache-Inhalte mitspielen können.

            dedlfix.

      2. die internen funktionen werden aber hoffentlich wesentlich schneller in der ausfuehrung sein.

        Tja das möchte man meinen. Und doch stoße ich immer wieder über solche Artikel:
        http://www.phpgangsta.de/php-in_array-die-performance-bremse

        Trifft in diesem Fall vielleicht nicht zu, dennoch bin ich vorsichtiger geworden einfach jeden Mist den php so anbietet zu nehmen. Außerdem sind die 3-4 Zeilen schneller geschrieben als man im php Handbuch nachguckt - wie heißt die Funktion nochmal, wie übergibt man die Parameter genau. Vor allem bei Funktionen die man nicht ständig braucht.

        Also nicht falsch verstehen, wenn man den Code schneller und übersichtlicher machen kann dann ist das eine super Sache. Dass muss aber immer abgewägt werden.

        Gruß
        der letzte Arbeitstag vor dem Urlaub YEAH
        T-Rex

        1. Tach!

          Und doch stoße ich immer wieder über solche Artikel:
          http://www.phpgangsta.de/php-in_array-die-performance-bremse
          Trifft in diesem Fall vielleicht nicht zu, dennoch bin ich vorsichtiger geworden einfach jeden Mist den php so anbietet zu nehmen.

          Das ist kein Mist, sondern geht auch in anderen Systemen nicht besser. Er hat da eine unsortierte Liste und will Duplikate vermeiden. Dass dazu für jeden Eintrag die gesamte Liste durchlaufen werden muss, ist nur logisch und dauert bei entsprechender Größe eben.

          Außerdem sind die 3-4 Zeilen schneller geschrieben als man im php Handbuch nachguckt -

          Das Problem bekommst du in der Form auch nicht mit 3-4 eigenen Zeilen gelöst. Da hilft nur die Liste sortiert vorliegen zu haben, dann geht das Suchen ratz-fatz. Allerdings hilft eine sortierte Liste dem in_array() nicht, weil es nichts von der Sortiertheit weiß und deshalb auch weiterhin nur alles durchlaufen kann. Die Lösung wäre ganz einfach mit PHP-Bordmitteln erreichbar, warum sie funktioniert steht in den Kommentaren des Artikels. Wenn die Werte als Keys abgelegt werden, kommt PHPs interne Speicherung als Hash-Map zum Tragen. Da reicht ein einfaches $array[$value] = 1; zum Hinzufügen, weil PHP selbst die Eindeutigkeit der Keys sicherstellt. Und das geht in der intern sortiert vorliegenden Liste eben sehr schnell.

          wie heißt die Funktion nochmal, wie übergibt man die Parameter genau. Vor allem bei Funktionen die man nicht ständig braucht.

          Du solltest dir eine Programmierumgebung zulegen, die Codevervollständigung kennt und Hinweise zu den Parametern einblenden kann. Das ist noch performanter als die Eigenentwicklung.

          dedlfix.

  3. Hallo,

    Das bedeutet ja, daß ich am Ende der Aufzählung 1 Komma zuviel habe, weshalb ich eine weitere for Schleife einbaue, die mir das Komma wegläßt, falls $Einzel das letzte Element des Arrays war.

    Gibt es dazu eine schlankere Lösung?

    Klar: $aufzaehlung = trim($aufzaehlung,",");

    Gast