String mit Platzhaltern durch verschiedene Arrays ersetzen

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • String mit Platzhaltern durch verschiedene Arrays ersetzen

    Hallo,

    ich schon wieder, ich habe mal wieder ein Problem mit assoziativen Arrays.
    Folgendes soll passieren:

    ich habe einen String: Das ist der String #1 #2

    Die #1 und #2 dienen Dabei als Platzhalter.

    Jetzt habe ich ein Array:

    PHP-Code:
    Array
    (
        [
    0] => eins
                  zwei
                  drei
        
    [1] => one
                  two
                  three

    Jetzt möchte ich in der Schleife die beiden Platzhalter durch die Inhalte des Array ersetzen, dabei gilt Array[0] für #1 und Array[1] #2.

    Ich nutze folgendes Script dazu:

    PHP-Code:
        public function addKeywords(&$lines$keyword) {
            if (!
    is_array($lines)) {
                
    $new_lines = array($lines);
            }

            
    $keywords $this->keywordArray($keyword); // Macht aus dem Inhalt einzelne Arrays
            
    for ($i 0$i < (count($new_lines)); $i++) {
                
    $value substr($new_lines[$i], strpos($new_lines[$i], "#")+11);
                    foreach (
    $keywords[$value-1] as $key => $val) {
                            
    $new_lines[] = str_replace("#".$value$val$new_lines[$i]);
                    }
                }
            return 
    $new_lines;
        } 
    Diese Funtion wamdelt den Inhalt des Keyword Arrays in ein Multidimensionales Array.
    PHP-Code:
        public function keywordArray($key) {
            
    $array = array();
            foreach (
    $key as $value) {
                if (!empty(
    $value[0])) {
                    
    $array[]= explode("\n"$value);
                }
            }
            return 
    $array;
        } 
    Ich erhalte zwar eine Ausgabe mit den richtigen Werten, aber mit sehr vielen Fehlern:
    Code:
    Warning:  Invalid argument supplied for foreach() in /media/sda3/xampp/xampp/htdocs/class.adwords.php on line 13
    
    
    
    Warning:  Invalid argument supplied for foreach() in /media/sda3/xampp/xampp/htdocs/class.adwords.php on line 13
    
    
    
    Warning:  Invalid argument supplied for foreach() in /media/sda3/xampp/xampp/htdocs/class.adwords.php on line 13
    
    
    
    Warning:  Invalid argument supplied for foreach() in /media/sda3/xampp/xampp/htdocs/class.adwords.php on line 13
    
    
    
    Warning:  Invalid argument supplied for foreach() in /media/sda3/xampp/xampp/htdocs/class.adwords.php on line 13
    
    
    
    Warning:  Invalid argument supplied for foreach() in /media/sda3/xampp/xampp/htdocs/class.adwords.php on line 13
    
    
    
    Warning:  Invalid argument supplied for foreach() in /media/sda3/xampp/xampp/htdocs/class.adwords.php on line 13
    
    
    
    Warning:  Invalid argument supplied for foreach() in /media/sda3/xampp/xampp/htdocs/class.adwords.php on line 13
    
    
    
    Warning:  Invalid argument supplied for foreach() in /media/sda3/xampp/xampp/htdocs/class.adwords.php on line 13
    
    Array
    (
        [0] => Keyword von #1 #2
        [1] => Keyword von eins
     #2
        [2] => Keyword von zwei
     #2
        [3] => Keyword von drei #2
    [COLOR="Red"]    [4] => Keyword von eins one
        [5] => Keyword von eins two
        [6] => Keyword von eins three
        [7] => Keyword von zwei one
        [8] => Keyword von zwei two
        [9] => Keyword von zwei three
        [10] => Keyword von drei one
        [11] => Keyword von drei two
        [12] => Keyword von drei three[/COLOR]
    )
    Die rot markierten sind das was ich will, aber ich verstehe die Fehlermeldungen der foreach Schleife nicht.

    Danke für die Tipps.

    Grüße Michael

  • #2
    Da aus deinem Code weder hervorgeht, wie und womit die Funktionen aufgerufen werden, noch welche die besagte Zeile 13 ist, ist dein Problem für mich so nicht nachvollziehbar.

    Davon abgesehen sind keine Bemühungen deinerseits erkennbar, diesen Fehlern auf den Grund zu gehen, weswegen ich geneigt bin, da einfach mal lapidar Faulheit zu unterstellen.

    Also, setz dich auf deinen Hintern, guck dir die Zeile 13 nochmal an und schieb davor einen Test ein:

    Code:
    if (!is_array($[I]variable[/I])) { throw new Exception(var_export($[I]variable[/I], true)); }
    Der Vorteil ist, dass das Skript sofort abgebrochen wird und du siehst, was denn nun wirklich in $variable steht. Dann analysierst du, wo die herkommt und wie es sein kann, dass es kein Array geworden ist.

    Bevor du das nicht gemacht hast, brauchst du dich hier eigentlich nicht wieder melden. Das ist übrigens nicht nur ne Macke von mir, sondern steht auch in den Forenregeln.

    Wenn danach noch Fragen auftauchen, kannst du die natürlich gerne stellen.

    Gruß,

    Anja
    [COLOR="DarkSlateGray"]Hast du die [COLOR="DarkSlateGray"]Grundlagen zur Fehlersuche[/color] gelesen? Hast du Code-Tags benutzt?
    Hast du als URL oder Domain-Beispiele example.com, example.net oder example.org benutzt?
    Super, danke!
    [/COLOR]

    Kommentar


    • #3
      Ich habe damit schon den ganzen Tag verbracht, aber ich bekomme keine Idee wie ich das Multidimensionale Array auf meinen String anwende.

      Gedacht war die Sache ja so, dass ich einen String habe welchen ich durch eine Schleife laufen lasse und den ersten Platzhalter tausche, den jeweils veränderten String schreibe ich in ein Array.

      Dann sollte das Array mit jeweils den gespeicherten Strings durch die selbe Schleife laufen und wieder die veränderten Strings in das selbe Array schreiben, so das das Array immer länger wird und je nachdem wieviel Platzhalter drin sind, so oft müsste die Schleife durchlaufen werden -> also denke ich, dass es sich eben die Funktion so lange selbst aufruft, bis keine Platzhalter mehr enthalten sind.

      Zum Aufruf des Scriptes ist nur zu sagen, dass es in einem php-Script eingebunden ist und wie folgt angesprochen wird:

      PHP-Code:
      $adwords = new adwords();
      ini_set('memory_limit','128M');
      error_reporting(E_ALL ^E_NOTICE);

      if (
      $_POST) {
          
      print_r ($adwords->addKeywords($_POST['campaign'], $_POST['key']));

      Die besagte Zeile 13:
      PHP-Code:
      13                foreach ($keywords[$value-1] as $key => $val) {
      14                        $new_lines[] = str_replace("#".$value$val$new_lines[$i]);
      15                
      Ich habe Deine Prüfung mal davor gesetzt und erhalte jetzt folgende Meldung:
      Code:
      Fatal error:  Uncaught exception 'Exception' with message 'NULL' in /media/sda3/xampp/xampp/htdocs/class.adwords.php:13
      Stack trace:
      #0 /media/sda3/xampp/xampp/htdocs/index.php(38): adwords->addKeywords('Keyword von #1 ...', Array)
      #1 {main}
        thrown in /media/sda3/xampp/xampp/htdocs/class.adwords.php on line 13
      Ich kann den Fehler jedoch nicht deuten, da ich die Nummer des Platzhalters wie folgt abfrage:
      PHP-Code:
      $value substr($new_lines[$i], strpos($new_lines[$i], "#")+11); 
      und damit die foreach Schleife mit dem passenden Keyword-Array füttere:
      eben die Zeile 13:
      PHP-Code:
      foreach ($keywords[$value-1] as $key => $val) { 
      Eigentlich sollte ja an der Stelle das Array mit dem Key 0 im ersten Durchlauf durch die Schleife gezogen werden, also quasi :
      PHP-Code:
          [0] => Array
              (
                  [
      0] => eins
                  
      [1] => zwei
                  
      [2] => drei
              

      Also sollte die Schleife drei Durchläufe haben, hat Sie aber nicht.

      Da ich nicht so erfahren bin, versuche ich hier halt Ideen zu Sammeln, aber wenn ich über Stunden hänge, dann versuch ich halt mein Glück im Forum.
      Das hat nichts mit Faulheit zu tun.

      Aber trotzdem Danke!
      Michael
      Zuletzt geändert von francosdad; 12.09.2009, 00:27.

      Kommentar


      • #4
        Zitat von francosdad Beitrag anzeigen
        Code:
        Fatal error:  Uncaught exception 'Exception' with message 'NULL' in /media/sda3/xampp/xampp/htdocs/class.adwords.php:13
        Stack trace:
        #0 /media/sda3/xampp/xampp/htdocs/index.php(38): adwords->addKeywords('Keyword von #1 ...', Array)
        #1 {main}
          thrown in /media/sda3/xampp/xampp/htdocs/class.adwords.php on line 13
        Ich kann den Fehler jedoch nicht deuten
        Und den Inhalt welcher Variablen hast du dir jetzt mit dieser extra zu diesem Zweck eingebauten Exception ausgeben lassen?

        Wenn es der derer ist, die im Foreach auf der nächsten Zeile als erster Parameter verwendet wird - dann wäre es ja nicht so gut, wenn als Wert hier NULL rauskommt bei der message der Exception. NULL ist schliesslich nicht besonders Array, und damit auch als erster Parameter für Foreach denkbar ungeeignet ...
        I don't believe in rebirth. Actually, I never did in my whole lives.

        Kommentar


        • #5
          Jetzt kommen wir doch der Sache aber schon viel näher. Du hast schonmal angegeben, wo es passiert und wo die Variable herkommt. Zufrieden bin ich zwar noch nicht 100%ig, aber wenn du es gleich auf die Art gepostet hättest, hätte ich ich vermutlich gar nicht gemeckert

          Zitat von francosdad Beitrag anzeigen
          PHP-Code:
          $value substr($new_lines[$i], strpos($new_lines[$i], "#")+11); 
          Welchen Wert hat $value nach dieser Zeile?

          Zitat von francosdad Beitrag anzeigen
          Code:
          Uncaught exception 'Exception' with message 'NULL'
          Nun wissen wir schonmal, dass $keywords[$value-1] kein Array, sondern null ist. Das kann 3 Gründe haben:

          1.) $value ist falsch und deswegen wird der index im Array nicht gefunden
          2.) Das Array hat einen Fehler, insofern dass der entsprechende Index da sein müsste, es aber nicht ist
          3.) $keywords ist aus irgendeinem Grund nicht mal ein Array

          Das kriegst du übrigens wieder raus, wenn du das throw-Statement von vorhin so abänderst:

          PHP-Code:
          if (!is_array($keywords[$value-1])) { throw new Exception(var_export(array("value" => $value"keywords" => $keywords), true)); } 
          Gruß,

          Anja
          [COLOR="DarkSlateGray"]Hast du die [COLOR="DarkSlateGray"]Grundlagen zur Fehlersuche[/color] gelesen? Hast du Code-Tags benutzt?
          Hast du als URL oder Domain-Beispiele example.com, example.net oder example.org benutzt?
          Super, danke!
          [/COLOR]

          Kommentar


          • #6
            Also ich habe die Methode jetzt nochmal komplett umgebaut und sie lautet jetzt:
            PHP-Code:
                private function addKeywords($lines$keyword) {
                    global 
            $result;
                    
            $array_final = array();

                    
            $keywords $this->keywordArray($keyword);
                    if (!
            is_array($lines)) {
                        
            $array = array($lines);
                    } else {
                        
            $array $lines;
                    }

                    foreach (
            $array as $key => $value) {
                        if (
            substr_count($value"#") > 1) {
                            
            $array $this->replaceWord($value$keywords);
                            
            $this->addKeywords($array$keyword); //Hier ruft sich die Methode selbst wieder auf, wenn noch mehr als ein Platzhalter im String ist.
                        
            } else {
                            
            $array_final array_merge($this->replaceWord($value$keywords), $array_final);
                        }
                    }

                    if (
            count($array_final) > 1) {
                        
            $result[] = $array_final;
                    }
                    return 
            $result;
                } 
            Das Problem ist jetzt, dass durch den rekursiven Aufruf der Funktion bei jedem Durchlauf ein Array geliefert wird. D.h bei drei Platzhaltern werden auch drei einzelne Arrays erzeugt, die sich bei jedem Durchlauf überschreiben.
            Um diese Abzufangen habe ich jetzt die Array Variable $result auf Global gesetzt.

            Damit entsteht aber das Problem, dass das $result Array nicht gelöscht wird.
            Wie könnte ich denn die Durchläufe sonst abfangen und in Arrays speichern?

            Ich habe da schon ein Haufen Tests gehabt, aber ich habe immer nur den letzten Array zurück geliefert bekommen.

            Wenn ich $result nicht auch Global setzte wird mir also immer nur der letzte Durchgang als Return geliefert.

            Zur Ausgabe habe ich mal das $result Global entfern und lasse $result mal über print_r ausgeben. Das Resultat sieht bei drei Platzhaltern dann wie folgt aus:
            Code:
            Array
            (
                [0] => Array
                    (
                        [0] => Kombination eins three un
                        [1] => Kombination eins three deux
                        [2] => Kombination eins three trios
                        [3] => Kombination eins two un
                        [4] => Kombination eins two deux
                        [5] => Kombination eins two trios
                        [6] => Kombination eins one un
                        [7] => Kombination eins one deux
                        [8] => Kombination eins one trios
                    )
            
            )
            Array
            (
                [0] => Array
                    (
                        [0] => Kombination zwei three un
                        [1] => Kombination zwei three deux
                        [2] => Kombination zwei three trios
                        [3] => Kombination zwei two un
                        [4] => Kombination zwei two deux
                        [5] => Kombination zwei two trios
                        [6] => Kombination zwei one un
                        [7] => Kombination zwei one deux
                        [8] => Kombination zwei one trios
                    )
            
            )
            Array
            (
                [0] => Array
                    (
                        [0] => Kombination drei three un
                        [1] => Kombination drei three deux
                        [2] => Kombination drei three trios
                        [3] => Kombination drei two un
                        [4] => Kombination drei two deux
                        [5] => Kombination drei two trios
                        [6] => Kombination drei one un
                        [7] => Kombination drei one deux
                        [8] => Kombination drei one trios
                    )
            
            )
            Diese einzelnen Arrays sollten in einem Array gefangen und als return geliefert
            werden.

            Danke für die Hinweise.

            Grüsse
            Michael

            Kommentar


            • #7
              Hallo,

              es sieht so aus als ob es da noch prinzipielle Verständnisprobleme bezüglich rekursiver Funktionen und derer Verwendung gäbe.

              Lies dir mal diesen Thread komplett durch. Ich bin sicher, dass das auch in deinem Falle hilfreich ist. Eine Art Grundgerüst für diese Art von Problemen ist da auch dabei.

              Gruß,

              Amica
              [COLOR="DarkSlateGray"]Hast du die [COLOR="DarkSlateGray"]Grundlagen zur Fehlersuche[/color] gelesen? Hast du Code-Tags benutzt?
              Hast du als URL oder Domain-Beispiele example.com, example.net oder example.org benutzt?
              Super, danke!
              [/COLOR]

              Kommentar


              • #8
                Bei den Verständnisproblemen stimme ich dir vollkommen zu, jedoch liegt das Problem des Verständnisses darin, dass in Deinem Thread die Standardlösung für Rekursion dargestellt wird, diese verstehe ich.

                In diesem Fall ist aber die Rekursion umgekehrt und zwar will ich das mal Skizzieren:

                Startstring: Das ist der Startstring #1 #2 #3

                Array für den ersten Platzhalter: array(eins, zwei, drei);
                Array für den zweiten Platzhalter: array(one, two, Three);
                Array für den dritten Platzhalter: array(un, deux, trios);

                Jetzt besteht die Aufgabe darin, aus dem ersten Platzhalter drei Arrays aus dem Array des ersten Platzhalter zu machen und jeweils aus jedem erzeugten Array wieder mit den Platzhalter Arrays multiplizieren.

                Das heißt in diesem Fall würden aus dem Startstring ein Array enstehen mit 27 Elementen.

                Also hab ich mir gedacht ich gebe den String in die Methode ein und mache daraus ein Array mit einem Element:
                PHP-Code:
                        if (!is_array($lines)) {
                            
                $array = array($lines);
                        } else {
                            
                $array $lines;
                        } 
                Dann lasse ich eine Foreach-Schleife laufen und frage ob mehr als ein Platzhalter drin ist:
                PHP-Code:
                foreach ($array as $key => $value) {
                            if (
                substr_count($value"#") > 1) {
                                
                $array $this->replaceWord($value$keywords);
                                
                $this->addKeywords($array$keyword); 
                Wenn ja, dann tausche mit der Methode $this->replaceWord den ersten Platzhalter gegen die ersten drei Arrays und dann ruft die Methode sich selbst wieder auf und übergibt das 3er Array in diese Methode.

                Wenn dann alle Platzhalter getauscht sind und nur einer übrig ist:
                PHP-Code:
                } else {
                                
                $array_final array_merge($this->replaceWord($value$keywords), $array_final);
                            } 
                Hier wird der $final_array aus dem in die Methode gegebenen Array mit dem letzten drei Arrays zusammengesetzt.

                Wenn ich mir das jetzt in einer globalen Variable in einer Klasse zwischenspeichere und diese nach Ausführung wieder lösche, dann gehts zumindest.

                Ich habe ein Problem beim Verständnis bei der Adaption; bsplw. wie aus Deinem Thread, einer normalen Rekursion aus meine Aufgabenstellung anzuwenden.

                Das Klassiker wie ein Verzeichnisbaum oder das Auslesen von Verzeichnissen basiert ja auf durchzählen bis zum Ende und sich dann rekursiv nach Vorn zu bewegen.

                In meinem Fall ist das ja keine Rekursion in diesem Sinne sondern eine Multiplikation, denn ich suche mir den ersten Aktionspunkt, baue daraus ein oder mehrere Ergebnisse in ein Array und lasse jedes Element nocheinmal durch diese Funktion laufen.

                Und ich habe den Eindruck das das doch etwas kompliziert ist und ich bin ja eher auf der Suche nach einer Anregung wie ich das ganze Skizzieren kann bzw. wie man eine klassische Rekursion darauf anwenden kann.

                Meine Lösung funktioniert zwar erstmal, aber ich denke es ist eine Schlechte.

                Ich möchte allerdings gerne auch eine saubere Lösung erreichen.

                Danke und Grüße
                Michael

                Kommentar


                • #9
                  Zitat von francosdad Beitrag anzeigen
                  jedoch liegt das Problem des Verständnisses darin, dass in Deinem Thread die Standardlösung für Rekursion dargestellt wird, diese verstehe ich.
                  Genau diese Standardlösung ist aber auch in deinem (komplexeren) Fall immer noch die Basis und das ignorierst du. Wenn eine rekursive Funktion einen Rückgabewert hat - und das sollte sie -, muss der auch verarbeitet werden, z. B. mit array_merge und genau das hast du nicht gemacht:

                  Zitat von francosdad Beitrag anzeigen
                  PHP-Code:
                  foreach ($array as $key => $value) {
                              if (
                  substr_count($value"#") > 1) {
                                  
                  $array $this->replaceWord($value$keywords);
                                  
                  $this->addKeywords($array$keyword); // Rückgabe geht ins Nirvana 
                  Dieser Umstand führt dann dazu, dass dir dann zusätzliche Krücken wie global als einzige Möglichkeit erscheinen.
                  [COLOR="DarkSlateGray"]Hast du die [COLOR="DarkSlateGray"]Grundlagen zur Fehlersuche[/color] gelesen? Hast du Code-Tags benutzt?
                  Hast du als URL oder Domain-Beispiele example.com, example.net oder example.org benutzt?
                  Super, danke!
                  [/COLOR]

                  Kommentar


                  • #10
                    Combie hat in einem ähnlichen Thema diesen Code gepostet.

                    Was ich neidlos anerkennen muss, ist, dass ich zwar auch einen Algorithmus dafür hatte, aber combies Variante mehr als doppelt so schnell ist (Benchmark mit 1000 Aufrufen und dabei jeweils verschieden großen Arrays).

                    An deiner Stelle würde ich also das verwenden und dann das Ergebnisarray durchiterieren und mit str_replace auf deine Platzhalter anwenden.

                    Ein weiterer Vorteil (neben der Schnelligkeit) ist die größere Modularität. Dein Code ist monolithisch und bei einem ähnlichen Problem schreibst du den trotzdem komplett neu. Mit der gerade erwähnten Variante hast du schon für die Zukunft vorgesorgt.

                    Gruß,

                    Amica
                    [COLOR="DarkSlateGray"]Hast du die [COLOR="DarkSlateGray"]Grundlagen zur Fehlersuche[/color] gelesen? Hast du Code-Tags benutzt?
                    Hast du als URL oder Domain-Beispiele example.com, example.net oder example.org benutzt?
                    Super, danke!
                    [/COLOR]

                    Kommentar


                    • #11
                      Ja, ich weiß denn dieser Post ist auch von mir und der entscheidende Unterschied ist der, dass bei dem geannten Post alle mit allen Array kombiniert werden sollten ohne das ein vorgegebener String erhalten bleibt -> sprich auch die Reihenfolge ist hier wichtig.

                      In der genannten Variante muss ich mich nur durch die Array arbeiten und nicht durch einen festen String.

                      Aber das Problem lag genau an der Stelle wie @AmicaNoctis es gesagt hat, ich habe die Rückgabe einfach nicht weiterverarbeitet.

                      Dies habe ich jetzt abgeändert und es funktioniert Prima, deswegen vielen Dank und gute Nacht!

                      Und denkt dran -> Wählen gehen, auch wenn das Duell heute ziemlich blass war.

                      Gruss
                      Michael

                      Kommentar


                      • #12
                        Zitat von francosdad Beitrag anzeigen
                        Ja, ich weiß denn dieser Post ist auch von mir und der entscheidende Unterschied ist der, dass bei dem geannten Post alle mit allen Array kombiniert werden sollten ohne das ein vorgegebener String erhalten bleibt -> sprich auch die Reihenfolge ist hier wichtig.
                        Das mit dem Unterschied hab ich nicht ganz verstanden, dort schriebst du:
                        Beispielsweise:
                        eins one alpha
                        eins one beta
                        eins one omega
                        eins two alpha
                        eins two beta
                        ... usw.
                        ... und hier:
                        [4] => Keyword von eins one
                        [5] => Keyword von eins two
                        [6] => Keyword von eins three
                        [7] => Keyword von zwei one
                        [8] => Keyword von zwei two
                        [9] => Keyword von zwei three
                        [10] => Keyword von drei one
                        [11] => Keyword von drei two
                        [12] => Keyword von drei three
                        Das sieht doch trotzdem ziemlich ähnlich aus.

                        Naja, wenn es jetzt funktioniert, ist ja gut.
                        [COLOR="DarkSlateGray"]Hast du die [COLOR="DarkSlateGray"]Grundlagen zur Fehlersuche[/color] gelesen? Hast du Code-Tags benutzt?
                        Hast du als URL oder Domain-Beispiele example.com, example.net oder example.org benutzt?
                        Super, danke!
                        [/COLOR]

                        Kommentar


                        • #13
                          Es funktioniert und das auch ziemlich schnell.

                          Das ist auch ziemlich ähnlich, der Unterschied ist jedoch, dass die Kombination aus dem ersten Post von keiner Bedingung die das einzelne Element enthält abhängt und der zweite das ein Vorgegebener String durchgearbeitet werden muss.

                          Ob das jetzt so ein großer Unterschied ist, ist natürlich fraglich, aber Tatsache ist, dass der Aufbau und das Prinzip ja trotzdem jetzt einer rekursiven Funktion entspricht.

                          Damit will ich sagen, dass es jetzt funktioniert und meiner Meinung nach auch effizient, aber ich mich Verbesserungsvorschlägen auf keinen Fall entziehen möchte.

                          Grüsse
                          Michael

                          Kommentar

                          Lädt...
                          X