Maik W. aus E.: array_search rekursiv einsetzen

Tach zusammen,

ich verwende ein Array, ähnlich dem von Alexander Brock zur Darstellung einer Verzeichnisstruktur:

  
$entries = array (  
  array (  
  'href'  => 'eins',  
  'text'  => 'Erster Punkt',  
  'title' => 'Erster Punkt'  
  ),  
  array (  
  'href'  => 'zwei',  
  'text'  => 'Zweiter Punkt',  
  'title' => 'Zweiter Punkt',  
   array (  
   'href'  => 'zweieins',  
   'text'  => '',  
   'title' => '',  
   ),  
   array (  
   'href'  => 'zweizwei',  
   'text'  => '',  
   'title' => ''  
  ),  
   array (  
   'href'  => 'zweidrei',  
   'text'  => '',  
   'title' => '',  
   ),  
  
  ),  
  
  
  array (  
  'href'  => 'drei',  
  'text'  => '',  
  'title' => '',  
   array (  
   'href'  => 'dreieins',  
   'text'  => '',  
   'title' => '',  
   ),  
   array (  
   'href'  => 'dreizwei',  
   'text'  => '',  
   'title' => '',  
   ),  
  ),  
);  

Jetzt lasse ich einen vorgegebenen Wert von 'href' auf das Array los und möchte mittels array_search feststellen, ob mein suchbegriff darin vorkommt. Da array_search() ja keine mehrdimensionalen Arrays durchsucht, habe ich einige Beispiele der Benutzer von der Manualseite ausprobiert, um auch mehrdimensionale Array zu durchsuchen, allerdings klemmen sie alle irgendwo..  Am erfolgreichsten war noch die Funktion

  
 function multiArraySearch($needle, $haystack){  
       $value = false;  
       $x = 0;  
       foreach($haystack as $temp){  
                 $search = array_search($needle, $temp);  
                 if (strlen($search) > 0 && $search >= 0){  
                     $value[0] = $x;  
                   $value[1] = $search;  
                     }  
                 $x++;  
           }  
   return $value;  
  }  

allerdings kommt die nur bis zur "ersten Ebene"... Mir ist es nicht gelungen, diese Funktion rekursiv aufzurufen, vielleicht habe ich einfach zu viel herumprobiert. Erschwerend kommt hinzu, daß ich dann, wenn auch Treffer der zweiten Eben funktionieren, ich den Wert aus 'href' der übergeordneten Ebene brauche...

Kann jemand helfen?

Danke und
http://www.gruss-aus-essen.de

Maik

--
Diese Dauerleihgabe wird Ihnen präsentiert von ROMY!
Maik. W. aus E. sagt Dankeschön ;-)
  1. hi,

    array (
      'href'  => 'zwei',
      'text'  => 'Zweiter Punkt',
      'title' => 'Zweiter Punkt',
       array (
       'href'  => 'zweieins',

      
    Warum legst du das hier als 'zweieins' ab?  
      
    Da es sich eine Ebene Unterhalb von 'zwei' befindet, würde 'eins' an dieser Stelle doch ausreichen - wenn man die Datenstruktur entsprechend aufbaut.  
    Also bspw. die "Kindelemente" in einem Unter-Array ablegen.  
      
    ~~~php
    Array  
    (  
        [0] => Array  
            (  
                [href] => eins  
                [text] => Erster Punkt  
                [title] => Erster Punkt  
                [kinder] => Array  
                    (  
                        [0] => Array  
                            (  
                                [href] => eins  
                                [text] => Zweiter Punkt  
                                [title] => Zweiter Punkt  
                            )  
                        [1] => Array  
                            (  
                                [href] => zwei  
                                [text] =>  
                                [title] =>  
                            )  
                    )  
            )  
    )
    

    Jetzt lasse ich einen vorgegebenen Wert von 'href' auf das Array los und möchte mittels array_search feststellen, ob mein suchbegriff darin vorkommt.

    Wenn du nach 'zwei/eins' suchen möchtest, bräuchtest du das nur aufzusplitten - und dann schauen, ob es auf oberster Ebene einen Eintrag 'zwei' gibt, der dann wiederum ein Kindelement 'eins' hat (, der dann wiederrum ...)

    Und noch angebrachter wäre es m.E., dafür gleich eine Klasse zu erstellen, anstatt das in Arrays abzulegen, die den Eigenschaften nur eine gewisse Struktur, aber keine Bedeutung geben können.

    gruß,
    wahsaga

    --
    /voodoo.css:
    #GeorgeWBush { position:absolute; bottom:-6ft; }
    1. Tach auch wahsaga,

      array (
        'href'  => 'zwei',
        'text'  => 'Zweiter Punkt',
        'title' => 'Zweiter Punkt',
         array (
         'href'  => 'zweieins',

      
      >   
      > Warum legst du das hier als 'zweieins' ab?  
      
      Das war jetzt nur ein Beispiel... Ein echter "Baum" sieht so aus:  
      ~~~php
        
      $entries = array (  
        array (  
        'href'  => 'nachrichten',  
        'text'  => 'Nachrichtenarchiv',  
        'title' => 'Sammlung älterer Nachrichten'  
        ),  
        array (  
        'href'  => 'ueber_uns',  
        'text'  => 'Über uns',  
        'title' => 'Wissenswertes über uns',  
         array (  
         'href'  => 'auftrag',  
         'text'  => 'Auftrag und Ziel',  
         'title' => '',  
         ),  
         array (  
         'href'  => 'ansprechpartner',  
         'text'  => 'Mitarbeiter',  
         'title' => '',  
         ),  
        ),  
        
        
        array (  
        'href'  => 'termine',  
        'text'  => 'Termine',  
        'title' => 'Unsere Terminkalender',  
         array (  
         'href'  => 'eigene',  
         'text'  => 'Eigene Veranstaltungen',  
         'title' => '',  
         ),  
         array (  
         'href'  => 'partner',  
         'text'  => 'Veranstaltungen mit Partnern',  
         'title' => '',  
         ),  
        ),  
        array (  
        'href'  => 'presse',  
        'text'  => 'Presse',  
        'title' => 'Informationspool für Journalisten',  
         array (  
         'href'  => 'meldungen',  
         'text'  => 'Meldungen',  
         'title' => 'Archiv aller Pressemeldungen',  
         ),  
         array (  
         'href'  => 'pressemappe',  
         'text'  => 'Pressemappe',  
         'title' => '',  
         ),  
         array (  
         'href'  => 'archiv',  
         'text'  => 'Bildarchiv',  
         'title' => 'Bildmaterial',  
         ),  
        ),  
        array (  
        'href'  => 'kontakt',  
        'text'  => 'Kontakt und Impressum',  
        'title' => 'Ihre Fragen und Anregungen',  
         array (  
         'href'  => 'impressum',  
         'text'  => 'Impressum',  
         'title' => 'Kontaktformular/E-Mail',  
         ),  
         array (  
         'href'  => 'anfahrt',  
         'text'  => 'Anfahrt',  
         'title' => 'Wegbeschreibung',  
         ),  
         array (  
         'href'  => 'datenschutz',  
         'text'  => 'Datenschutz',  
         'title' => 'Informationen zur Datensicherheit'  
         ),  
        ),  
        
        
      );  
      
      

      Da es sich eine Ebene Unterhalb von 'zwei' befindet, würde 'eins' an dieser Stelle doch ausreichen - wenn man die Datenstruktur entsprechend aufbaut.

      Vielleicht wird es jetzt etwas klarer...

      Jetzt lasse ich einen vorgegebenen Wert von 'href' auf das Array los und möchte mittels array_search feststellen, ob mein suchbegriff darin vorkommt.
      Wenn du nach 'zwei/eins' suchen möchtest, bräuchtest du das nur aufzusplitten - und dann schauen, ob es auf oberster Ebene einen Eintrag 'zwei' gibt, der dann wiederum ein Kindelement 'eins' hat (, der dann wiederrum ...)

      Ich möchte jetzt aber nach 'anfahrt' suchen, und wenn 'anfahrt' nicht in der "oberen Ebene" ist, auch noch den href-Wert des Elements haben, dessen Kind es ist...

      Und noch angebrachter wäre es m.E., dafür gleich eine Klasse zu erstellen, anstatt das in Arrays abzulegen, die den Eigenschaften nur eine gewisse Struktur, aber keine Bedeutung geben können.

      Gerne, aber wie?
      http://www.gruss-aus-essen.de

      Maik

      --
      Diese Dauerleihgabe wird Ihnen präsentiert von ROMY!
      Maik. W. aus E. sagt Dankeschön ;-)
      1. hi,

        Das war jetzt nur ein Beispiel... Ein echter "Baum" sieht so aus:

        Array  
        (  
            [0] => Array (...)  
            [1] => Array  
                (  
                    [href] => ueber_uns  
                    [text] => Über uns  
                    [title] => Wissenswertes über uns  
                    [0] => Array  
                        (  
                            [href] => auftrag  
                            [text] => Auftrag und Ziel  
                            [title] =>  
                        )  
          
                    [1] => Array  
                        (  
                            [href] => ansprechpartner  
                            [text] => Mitarbeiter  
                            [title] =>  
                        )
        

        auftrag und ansprechpartner liegen also unterhalb von ueber_uns.

        Da verstehe ich nicht, warum du die einfach als weiterer Arrays dranhängt - das bildet doch die Struktur kaum sinnvoll ab.

        Ich würde es wie gesagt so machen, dass ich für ueber_uns noch eine Eigenschaft "kindelemente" definiere - und _diese_ enthält dann in einem Array die darunter liegenden Ebenen.
        Statt also auf der selben Ebene wie die Eigenschaften href, text und title noch nichtssagende Eigenschaften mit den Schlüsseln 0 und 1 liegen zu haben, hätte ich parallel zu href, text und title noch eine Eigenschaft childs liegen - und _unterhalb_ dieser dann die Kinder (childs wäre also ein Array).

        Ich möchte jetzt aber nach 'anfahrt' suchen, und wenn 'anfahrt' nicht in der "oberen Ebene" ist, auch noch den href-Wert des Elements haben, dessen Kind es ist...

        Das wäre dann entweder ein Fall für einen rekursiven Alogrithmus, der sich "merkt" welchen Weg er gegangen ist - oder für einen Baum als Datenstruktur, der sich in beide Richtungen, von der Wurzel zu den Blättern, und von den Blättern zur Wurzel durchlaufen lässt. Es müsste also nicht nur an X die Information abgelegt werden, dass Y ein Kind von X ist - sondern auch an Y, dass X das Parent von Y ist.

        Und noch angebrachter wäre es m.E., dafür gleich eine Klasse zu erstellen, anstatt das in Arrays abzulegen, die den Eigenschaften nur eine gewisse Struktur, aber keine Bedeutung geben können.

        Gerne, aber wie?

        Na, definier dir ein Objekt mit entsprechenden Eigenschaften - href, title, text, childs, parent, ...
        Und hänge dann beim Aufbauen dieses Baums die Kindelemente in die Parents ein, und lasse die parent-Eigenschaft der Kinder auf das Parent verweisen.

        gruß,
        wahsaga

        --
        /voodoo.css:
        #GeorgeWBush { position:absolute; bottom:-6ft; }
        1. Tach auch wahsaga,

          hi,

          Das war jetzt nur ein Beispiel... Ein echter "Baum" sieht so aus:

          Array

          (
              [0] => Array (...)
              [1] => Array
                  (
                      [href] => ueber_uns
                      [text] => Über uns
                      [title] => Wissenswertes über uns
                      [0] => Array
                          (
                              [href] => auftrag
                              [text] => Auftrag und Ziel
                              [title] =>
                          )

          [1] => Array
                          (
                              [href] => ansprechpartner
                              [text] => Mitarbeiter
                              [title] =>
                          )

          
          >   
          > auftrag und ansprechpartner liegen also unterhalb von ueber\_uns.  
          
          Genau.  
            
          
          > Da verstehe ich nicht, warum du die einfach als weiterer Arrays dranhängt - das bildet doch die Struktur kaum sinnvoll ab.  
          
          Ach wahsaga, Strukturen sind so wie sie sind, weil sie so gewachsen sind... (Wie gesagt, das basiert auf der Menü-Funktion von Alexander) und wie gut die Strukturen sind, sieht man dann, wenn nachträglich weitere Anforderungen an sie gestellt werden...  
            
          
          > > Gerne, aber wie?  
          >   
          > Na, definier dir ein Objekt mit entsprechenden Eigenschaften - href, title, text, childs, parent, ...  
          > Und hänge dann beim Aufbauen dieses Baums die Kindelemente in die Parents ein, und lasse die parent-Eigenschaft der Kinder auf das Parent verweisen.  
          
          Wie oben schon gesagt, strukturell was zu ändern wäre \_sehr\_ aufwendig, da versuche ich doch lieber mit dem [Ansatz von dedlfix](https://forum.selfhtml.org/?t=147328&m=955856), die vorhandene Struktur abzuklappern.  
            
          Trotzdem Danke für Deine Mühe,  
            
          Gruß nach D., <http://www.gruss-aus-essen.de>  
            
          Maik
          
          -- 
          ![Diese Dauerleihgabe wird Ihnen präsentiert von ROMY!](http://www.gruss-aus-essen.de/selfforum/totes_huhn.jpg)  
          Maik. W. aus E. sagt Dankeschön ;-)  
          
          
  2. echo $begrüßung;

    Da array_search() ja keine mehrdimensionalen Arrays durchsucht, habe ich einige Beispiele der Benutzer von der Manualseite ausprobiert, um auch mehrdimensionale Array zu durchsuchen, allerdings klemmen sie alle irgendwo..

    Was hat dir denn an dem Vorschlag nicht gefallen? Das war von oben gesehen die erste, die einen Selbstaufruf enthielt, was für Rekursion eine essentielle Eigenschaft ist. Darunter folgen auch noch ein paar.

    [...] möchte mittels array_search feststellen, ob mein suchbegriff darin vorkommt. Da array_search() ja keine mehrdimensionalen Arrays durchsucht, [...]

    Es ist in den meisten PHP-Array-Fällen besser, den Begriff multidimensional zu meiden. Du hast ein Array, das einfache und komplexe Werte aufnehmen. Ein komplexer Wert kann seinerseits wieder einfache und komplexe Werte enthalten. Und das kann beliebig tief geschachtelt werden. Du hast also eine Baumstruktur.

    array_search() sucht nur die einfachen Elemente ab. Und die komplexen? Die müssen wir selbst durchlaufen. Gibt es eine Funktion, die nur alle einfachen oder nur alle komplexen Elemente aus einem Array suchen kann? Damit könnte man array_search() auf die einfachen Elemente loslassen und die komplexen Elemente gesondert behandeln. Eine solche Funktion ist mir noch nicht aufgefallen. Da wir sowieso durch alle Elemente laufen müssen, können wir uns array_search() gleich ganz klemmen und den Vergleich selbst durchführen. (Außerdem, so scheint es mir, willst du gar ncht alle Elemente durchsuchen, sondern nur welche mit einem bestimmten Key (z.B. alle href-Elemente). Dann wäre array_search() sowieso kontraproduktiv.)

    Was muss die Suchfunktion wissen? Das zu durchsuchende Array, den Suchbegriff, evtl. den zu durchsuchenden Key, und wenn ein Treffer gefunden wurde, wolltest du ja noch den Pfad dahin haben. Der lässt sich rückwärts nicht ermitteln, also muss der bisherige Pfad bei jedem hinabzusteigenden Level mitgegeben werden. So sähe eine passende Funktionssignatur aus:

    function mwe_search($haystack, $needle, $searchKey = null, $path = '', $sep = '/')

    Wie soll das Ergebnis aussehen? Willst du (a) alle Fundstellen, oder (b) nur den ersten Treffer? Für alle Fundstellen brauchst du ein Sammelbecken, z.B. ein Array, das entweder eine Klassenvariable sein kann oder eine globale Variable. Schöner wäre es, wenn die Funktion das Suchergebnis zurücklieferte, aber dafür muss dann auch noch ein Ergebnis-Array mit rumgeschleppt werden.
    Um nur den ersten Treffer zu ermitteln brauchst du eine Erfolgsanzeige, damit der Aufrufer weiß, dass er nun abbrechen kann. Wenn nichts gefunden wurde wäre das ein false, beim einem positiven Ergebnis wäre es der Pfad. Und der muss dann nach außen transportiert werden.

    Für alle key-value-Paare im $haystack musst du:

    • prüfen, ob value ein Array ist. In dem Fall muss der Pfad erweitert werden $path .= $sep . '...', und mwe_search() mit dem value als haystack aufgerufen werden. (b) In Abhängigkeit des Rückgabewertes muss die Funktion verlassen werden oder nicht.

    • Wenn kein Array vorliegt:
      -- Wenn $searchkey !== null ist:
      --- Wenn $searchKey gleich $key ist, vergleiche den Wert mit $needle. Bei Übereinstimmung (a) das Sammelarray ergänzen oder (b) Pfad zurückgeben (ggf. ergänzen)
      -- Ansonsten vergleiche den Wert mit $needle, und reagiere gleich wie oben.

    Wenn der $haystack durchlaufen ist, muss (a) einfach zurückkehren und (b) ein false zurückliefern.

    echo "$verabschiedung $name";

    1. Tach auch dedlfix,

      [...] möchte mittels array_search feststellen, ob mein suchbegriff darin vorkommt. Da array_search() ja keine mehrdimensionalen Arrays durchsucht, [...]

      Es ist in den meisten PHP-Array-Fällen besser, den Begriff multidimensional zu meiden. Du hast ein Array, das einfache und komplexe Werte aufnehmen. Ein komplexer Wert kann seinerseits wieder einfache und komplexe Werte enthalten. Und das kann beliebig tief geschachtelt werden. Du hast also eine Baumstruktur.

      Ja, ich weiß, ich habe bei meiner Archiv-Suche schon einen Beitrag von Dir gefunden, in dem es genau darum ging... Sorry, in meinem OP fehlten da die "Anführungszeichen"...

      array_search() sucht nur die einfachen Elemente ab. Und die komplexen? Die müssen wir selbst durchlaufen. Gibt es eine Funktion, die nur alle einfachen oder nur alle komplexen Elemente aus einem Array suchen kann? Damit könnte man array_search() auf die einfachen Elemente loslassen und die komplexen Elemente gesondert behandeln. Eine solche Funktion ist mir noch nicht aufgefallen. Da wir sowieso durch alle Elemente laufen müssen, können wir uns array_search() gleich ganz klemmen und den Vergleich selbst durchführen. (Außerdem, so scheint es mir, willst du gar ncht alle Elemente durchsuchen, sondern nur welche mit einem bestimmten Key (z.B. alle href-Elemente). Dann wäre array_search() sowieso kontraproduktiv.)

      Danke für den ausführlichen Hinweis, ich bin immer froh, wenn mir jemand den Hammer wegnimmt, weil man damit nun wirklich nicht sägen kann...

      Was muss die Suchfunktion wissen? Das zu durchsuchende Array, den Suchbegriff, evtl. den zu durchsuchenden Key, und wenn ein Treffer gefunden wurde, wolltest du ja noch den Pfad dahin haben. Der lässt sich rückwärts nicht ermitteln, also muss der bisherige Pfad bei jedem hinabzusteigenden Level mitgegeben werden. So sähe eine passende Funktionssignatur aus:

      function mwe_search($haystack, $needle, $searchKey = null, $path = '', $sep = '/')

      Wie soll das Ergebnis aussehen? Willst du (a) alle Fundstellen, oder (b) nur den ersten Treffer? Für alle Fundstellen brauchst du ein Sammelbecken, z.B. ein Array, das entweder eine Klassenvariable sein kann oder eine globale Variable. Schöner wäre es, wenn die Funktion das Suchergebnis zurücklieferte, aber dafür muss dann auch noch ein Ergebnis-Array mit rumgeschleppt werden.

      ich möchte (b) 8>)

      Um nur den ersten Treffer zu ermitteln brauchst du eine Erfolgsanzeige, damit der Aufrufer weiß, dass er nun abbrechen kann. Wenn nichts gefunden wurde wäre das ein false, beim einem positiven Ergebnis wäre es der Pfad. Und der muss dann nach außen transportiert werden.

      Für alle key-value-Paare im $haystack musst du:

      • prüfen, ob value ein Array ist. In dem Fall muss der Pfad erweitert werden $path .= $sep . '...', und mwe_search() mit dem value als haystack aufgerufen werden. (b) In Abhängigkeit des Rückgabewertes muss die Funktion verlassen werden oder nicht.

      • Wenn kein Array vorliegt:
        -- Wenn $searchkey !== null ist:
        --- Wenn $searchKey gleich $key ist, vergleiche den Wert mit $needle. Bei Übereinstimmung (a) das Sammelarray ergänzen oder (b) Pfad zurückgeben (ggf. ergänzen)
        -- Ansonsten vergleiche den Wert mit $needle, und reagiere gleich wie oben.

      Wenn der $haystack durchlaufen ist, muss (a) einfach zurückkehren und (b) ein false zurückliefern.

      Super, vielen Dank für diese ausführliche Antwort, ich werde mich umgehend hinsetzen und genau so eine mwe_search-Funktion bauen, das dürfte jetzt ja nicht mehr so schwierig sein...

      Danke und

      http://www.gruss-aus-essen.de

      Maik

      --
      Diese Dauerleihgabe wird Ihnen präsentiert von ROMY!
      Maik. W. aus E. sagt Dankeschön ;-)