rekursive Funktion umsortieren

Fragen zu allen Themen rund ums Programmieren außerhalb von phpBB können hier gestellt werden - auch zu anderen Programmiersprachen oder Software wie Webservern und Editoren.
bluebull
Mitglied
Beiträge: 11
Registriert: 29.09.2013 00:51

rekursive Funktion umsortieren

Beitrag von bluebull »

Hallo. Ich bin beim Erstellen eines Stammbaumes. Dazu habe ich eine mySQL Datenbank, welche ich rekursiv Abfrage:

Code: Alles auswählen

//funktion vorfahren

function ahnen($id,$generation,$level)
{

        if($generation < 4)
       {
        $generation++;
        $sql = "SELECT * FROM personen WHERE id = '$id'";
        $result = mysql_query($sql);
        $person=mysql_fetch_array($result);
        $vater = $person['vater_id'];
        $mutter = $person['mutter_id'];
        echo str_repeat('&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp',$level)."$person[nachname] $person[vorname] *$person[geburtsdatum]<br>";
            {
            ahnen($vater,$generation,$level+1);
            ahnen($mutter,$generation,$level+1);

            }
        }

 }

 ahnen($id,0,0);
Die Ausgabe erfolgt im Schema

Code: Alles auswählen

aktuelle Person
   Vater
      Opa
         Ur-Opa
             etc.
         ur-Oma
      Oma
   Mutter
ich möchte aber:

Code: Alles auswählen

Ur-Opa + Ur-Oma
    Opa + Oma
        Vater + Mutter
            akteulle Person
Wie bekomme ich das hin?

Danke und Gruss
Benutzeravatar
Nuramon
Mitglied
Beiträge: 250
Registriert: 05.02.2012 21:45
Wohnort: Solingen
Kontaktdaten:

Re: rekursive Funktion umsortieren

Beitrag von Nuramon »

Wie genau ist denn deine Datenbank aufgebaut, also welche Spalten gibt es?
id, vater, mutter, nachname, vorname, geburtsdatum
oder sowas?

Und möchtest du sowohl Oma und Opa von Vater als auch Oma und Opa von Mutter ausgeben lassen?
Das wären noch wichtige Fragen.

Und sonst erst den Rekursiven Aufruf, dahinter die Ausgabe, und die Einrückung aus der Rückgabe der rekursiven Methode ziehen. Männlich/weiblich als boolean übergeben und an den Namen dann ein je nachdem ein + oder ein Linebreak anhängen.
Das Pinke Forum
Das Pinke Forum - werde Teil einer freundlichen Community, die dir bei Fragen rund um Liebe, Sex, Ernährung, Schule oder bei Problemen aller Art zur Seite steht! Verfasse Beiträge, erstelle Threads und lern nette Leute kennen; kostenlos und toll betreut.
Benutzeravatar
cYbercOsmOnauT
Ehemaliges Teammitglied
Beiträge: 3820
Registriert: 18.02.2004 23:02
Wohnort: Göttingen
Kontaktdaten:

Re: rekursive Funktion umsortieren

Beitrag von cYbercOsmOnauT »

Wie die DB aufgebaut ist, ist eher irrelevant. Es ist eine klassische Baum-Rekursion. Sein Ansatz ist schon richtig, nur darf man da nicht sofort ausgeben, sondern packt die Fünde sortiert in ein Array und gibt diesem am Ende aus wenn man den Baum komplett durch hat. Sind ja bei der Aufgabe gerade mal 14 Verästelungen.
• prof. phpbb-Installation, Reparatur, Rettung nach Hackattacken, sowie PHP/JS Programmierung aller Art
Zend Certified Engineer, Linux Administrator und die Sicherheit von 34 Jahren Programmiererfahrung
• Interesse? Kontakt unter t.birduezen@web-coding.eu
bluebull
Mitglied
Beiträge: 11
Registriert: 29.09.2013 00:51

Re: rekursive Funktion umsortieren

Beitrag von bluebull »

danke für die schnellen antworten. meine datenbank ist tatsächlich mit id, nachname, vorname, geburtsdatum, ..., vater_id, mutter_id aufgebaut.

es werden aber noch mehr generationen dazukommen und ich frage sowohl die vaterseite als auch die mutterseite soweit bekannt ab.

ich werde eure vorschläge mal ausprobieren (sofern ich das hinbekomme) und mich dann wieder melden. vielen dank
bluebull
Mitglied
Beiträge: 11
Registriert: 29.09.2013 00:51

Re: rekursive Funktion umsortieren

Beitrag von bluebull »

Soweit so gut. Einige Sachen habe ich hinbekommen (manche nicht). Auch die Sortierung von unten nach oben stimmt nun.

Code: Alles auswählen

$id = '2';
$generationen = '12';

//Vorfahren funktion

function ahnen($id,$generation,$level)
{
global $generationen;
        if($generation < $generationen)
       {
        $generation++;
        $sql = "SELECT * FROM personen WHERE id = '$id'";
        $result = mysql_query($sql);
        $person=mysql_fetch_array($result);
        $vater = $person['vater_id'];
        $mutter = $person['mutter_id'];
            {
            ahnen($vater,$generation,$level+1);
            ahnen($mutter,$generation,$level+1);

            }

       echo str_repeat('&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp',$level)."$person[nachname] $person[vorname] *$person[geburtsdatum]<br>";
        }
 }

 ahnen($id,0,$generationen-1);
2 Probleme habe ich noch. Das eine ist, dass die "älteste Person" nun oben rechts ist (statt oben links) und das andere, dass ich exponentiel sternchen zwischen den Personen habe. Es schaut ungefähr so aus:

Code: Alles auswählen

                                                                                                                                    person *1640-00-00
                                                                                                                                    person  *0000-00-00
                                                                                                                              person  *0000-00-00
                                                                                                                                     *
                                                                                                                                     *
                                                                                                                              person  *0000-00-00
                                                                                                                        person  *0000-00-00
                                                                                                                                     *
                                                                                                                                     *
                                                                                                                               *
                                                                                                                                     *
                                                                                                                                     *
                                                                                                                               *
                                                                                                                        person  *0000-00-00
                                                                                                                  person  *1744-07-01
                                                                                                                                     *
                                                                                                                                     *
                                                                                                                               *
                                                                                                                                     *
                                                                                                                                     *
                                                                                                                               *
                                                                                                                         *
                                                                                                                                     *
                                                                                                                                     *
                                                                                                                   usw.
Leider bin ich noch sehr neu in PHP und mySQL und sehe den/die Fehler nicht. Ich danke euch für eure nette Hilfe.
Benutzeravatar
Nuramon
Mitglied
Beiträge: 250
Registriert: 05.02.2012 21:45
Wohnort: Solingen
Kontaktdaten:

Re: rekursive Funktion umsortieren

Beitrag von Nuramon »

Ich bin mal nett, hatte gerade das Bedürfnis, ein wenig an deinem Code rumzubasteln. Musste allerdings die Datenbankabfrage gegen ein Array austauschen zum Testen. Würde dir eh raten, lieber die Datenbank einmal auszulesen, in einem Array abzuspeichern, und damit zu arbeiten. Spart Abfragen an die Datenbank.

Mein Code sieht jetzt so aus:

Code: Alles auswählen

<?php

$id = 1;
$generationen = 12;

$personen = array(
    1 => array('name' => 'Person 1', 'vater_id' => 2, 'mutter_id' => 3),
    2 => array('name' => 'Vater 1', 'vater_id' => 4, 'mutter_id' => 5),
    3 => array('name' => 'Mutter 1', 'vater_id' => 6, 'mutter_id' => 7),
    4 => array('name' => 'Vater 2', 'vater_id' => 8, 'mutter_id' => 9),
    5 => array('name' => 'Mutter 2', 'vater_id' => 10, 'mutter_id' => 11),
    //6 => array('name' => 'Vater 2.2', 'vater_id' => 11, 'mutter_id' => 12),
    //7 => array('name' => 'Mutter 2.2', 'vater_id' => 12, 'mutter_id' => 13),
    );

//Vorfahren funktion

function ahnen($id, $generation, $is_vater)
{
    global $generationen, $personen;
    if($generation < $generationen)
    {
        $generation++;
        
        if(!isset($personen[$id]))
            return 0;
        //$sql = "SELECT * FROM personen WHERE id = '$id'";
        //$result = mysql_query($sql);
        //$person=mysql_fetch_array($result);
        $person = $personen[$id];
        $vater = $person['vater_id'];
        $mutter = $person['mutter_id'];
        {
            $level = ahnen($vater,$generation,true);
            ahnen($mutter,$generation,false);

        }

        if($is_vater)
            echo str_repeat('&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp',$level)."$person[name]";
        else
            echo '&nbsp+&nbsp' . "$person[name]<br>";
    }
    return $level + 1;
}

ahnen($id,0,true);

?>
Ausgabe ist:

Code: Alles auswählen

Vater 2 + Mutter 2
      Vater 1 + Mutter 1
            Person 1

Das Problem, was sich jetzt stellt, ist, wenn du den Stammbaum nicht nur in eine Richtung haben möchtest. Also wenn er etwa so aufgebaut sein soll:

Code: Alles auswählen

Vater 2 + Mutter 2          Vater 2.2 + Mutter 2.2
               Vater 1 + Mutter 1
                    Person 1
Kannst du bei meinem Code testen, indem du oben die beiden weiteren Array-Zeilen einkommentierst.
Das Problem hierbei ist einfach, dass du dann nicht sofort ausgeben darfst. Du musst gucken, wie viele parallel-Generationen existieren, und sie in eine Zeile zusammenbasteln, dann ausgeben.
Beste Lösung hier wäre wohl ein Array anzulegen über die Generationen und in denen die Leute in einem Array pro Generation einspeichern, statt sofort auszugeben. Allerdings besteht dann das Problem mit der Formatierung, die dann schwieriger wird, und was passiert, wenn ein Elternteil beispielweise keine Großeltern angegeben hat, eines aber schon.

Hoff aber die Grundidee ist klar?
Das Pinke Forum
Das Pinke Forum - werde Teil einer freundlichen Community, die dir bei Fragen rund um Liebe, Sex, Ernährung, Schule oder bei Problemen aller Art zur Seite steht! Verfasse Beiträge, erstelle Threads und lern nette Leute kennen; kostenlos und toll betreut.
Benutzeravatar
Nuramon
Mitglied
Beiträge: 250
Registriert: 05.02.2012 21:45
Wohnort: Solingen
Kontaktdaten:

Re: rekursive Funktion umsortieren

Beitrag von Nuramon »

Sorry für den Doppelpost, finde es aber unübersichtlich, das in einen zu hauen. Hab jetzt noch ein wenig geschraubt, dass es halbwegs geht. Schau mal hier

Code: Alles auswählen

<?php

$id = 1;
$generationen = 12;
$stammbaum = array();

$personen = array(
    1 => array('name' => 'Person 1', 'vater_id' => 2, 'mutter_id' => 3),
    2 => array('name' => 'Vater 1', 'vater_id' => 4, 'mutter_id' => 5),
    3 => array('name' => 'Mutter 1', 'vater_id' => 6, 'mutter_id' => 7),
    4 => array('name' => 'Vater 2', 'vater_id' => 8, 'mutter_id' => 9),
    5 => array('name' => 'Mutter 2', 'vater_id' => 10, 'mutter_id' => 11),
    6 => array('name' => 'Vater 2.2', 'vater_id' => 11, 'mutter_id' => 12),
    7 => array('name' => 'Mutter 2.2', 'vater_id' => 12, 'mutter_id' => 13),
    );

//Vorfahren funktion

function ahnen($id, $generation, $is_vater)
{
    global $generationen, $personen, $stammbaum;
    if($generation < $generationen)
    {
        $generation++;
        
        if(!isset($personen[$id]))
            return 0;
        //$sql = "SELECT * FROM personen WHERE id = '$id'";
        //$result = mysql_query($sql);
        //$person=mysql_fetch_array($result);
        $person = $personen[$id];
        $vater = $person['vater_id'];
        $mutter = $person['mutter_id'];
        {
            $level = ahnen($vater,$generation,true);
            ahnen($mutter,$generation,false);

        }

        if($is_vater)
        {
            $stammbaum[$generation][] = $person['name'];
        }
        else
        {
            $last_mother = $stammbaum[$generation][count($stammbaum[$generation])-1];
            $stammbaum[$generation][count($stammbaum[$generation])-1] = $last_mother . ' + ' . $person['name'];
        }
    }
    return $level + 1;
}

ahnen($id,0,true);

$row = 0;
foreach($stammbaum as $reihe)
{
    echo str_repeat('&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp',$row);
    foreach($reihe as $ahnenpaar)
    {
        echo $ahnenpaar . '&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp';
    }
    echo "<br />";
    $row = $row + 1;
}

?>
Ausgabe ist so:

Code: Alles auswählen

Vater 2 + Mutter 2      Vater 2.2 + Mutter 2.2      
                  Vater 1 + Mutter 1      
                                    Person 1      
Ich gebe es unten erst aus, sammel alles in der globalen Variable $stammbaum.
Hier müsstest du nur noch überarbeiten, dass leere Personen auch noch reingeschrieben werden, irgendwie, aber dann ohne +-Verknüpfung, da es sonst zu Formatierungsfehlern kommt. Musst da halt sowohl auf Vater als auch Mutter prüfen.
Oder stellst du sicher, dass der Baum vollständig ist? Dann würde es so gehen, wie es hier ist.
Formatierung sieht allerdings noch nicht so hübsch aus. Wird auch sehr schwierig. Da kommst du dann wohl nicht drumherum, Zeichen zu zählen und zu übergeben und darauf die exakten Abstände in Leerzeichen zu berechnen. Wird ein großer Aufwand, denke ich.
Das Pinke Forum
Das Pinke Forum - werde Teil einer freundlichen Community, die dir bei Fragen rund um Liebe, Sex, Ernährung, Schule oder bei Problemen aller Art zur Seite steht! Verfasse Beiträge, erstelle Threads und lern nette Leute kennen; kostenlos und toll betreut.
bluebull
Mitglied
Beiträge: 11
Registriert: 29.09.2013 00:51

Re: rekursive Funktion umsortieren

Beitrag von bluebull »

Sehr cool. Danke. Ich werde den Code durcharbeiten und dan Rückmeldung geben.
bluebull
Mitglied
Beiträge: 11
Registriert: 29.09.2013 00:51

Re: rekursive Funktion umsortieren

Beitrag von bluebull »

Hallo. Ja, die Darstellung war wirklich nicht optimal durchdacht. Ich habe mich jetzt für eine wesentlich einfachere Darstellung entschieden:

Code: Alles auswählen

vater ...
mutter ...
      vater des Vaters
      mutter des Vaters
            vater
      vater der mutter
      mutter der mutter
            mutter
                    aktuelle Person
                            ------------- andere abfrage---------------------
                            Kind 
                                Enkel
                            Kind
mein Code dazu

Code: Alles auswählen

//übergabe variablen
$id = 2;
$generationen = 12;

//darstellung

$spacer = '&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp';

//array

$query = mysql_query( "SELECT * FROM personen");
$personen = array();
while($row = mysql_fetch_assoc($query)){
    $personen []=$row;
}

//Vorfahren

function vorfahren($id,$generation,$level)
{
global $generationen, $spacer, $personen;
        if($generation < $generationen)
       {
        $generation++;
        $person = $personen[$id-1];
        $vater = $person['vater_id'];
        $mutter = $person['mutter_id'];

        if ($vater !== null){
        vorfahren($vater,$generation,$level-1);
        }
        if ($mutter !== null){
        vorfahren($mutter,$generation,$level-1);
        }
        echo str_repeat($spacer,$level)."$person[nachname] $person[vorname] *$person[geburtsdatum]\n<br>";
      }
 }
vorfahren($id,0,$generationen-1);

//aktuelle Person
$query = mysql_query("SELECT * FROM personen WHERE id = $id");
while($row = mysql_fetch_object($query))
         {
         echo str_repeat($spacer,$generationen-1)."<b>$row->nachname $row->vorname *$row->geburtsdatum</b>\n<br>";
         }

 
Wie kann ich die aktuelle Person in der Abfrage weglassen, damit ich diese durch eine separate Abfrage (wie im obigen Code) fett darstelen kann?
Benutzeravatar
Miriam
Mitglied
Beiträge: 12310
Registriert: 13.10.2004 07:18
Kontaktdaten:

Re: rekursive Funktion umsortieren

Beitrag von Miriam »

So könnte es klappen:

Code: Alles auswählen

$personen = array();
$generation = 0;

//übergabe variablen
$id = 2;
$generationen = 12;

//darstellung
$spacer = '&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp';

//array
$query = mysql_query( "SELECT * FROM personen");


while($row = mysql_fetch_assoc($query))
{
    $personen[] = $row;
}

//Vorfahren
function vorfahren($id, $generation, $level)
{
    global $generationen, $spacer, $personen;

    if($generation < $generationen)
    {
        $generation++;
        $person = $personen[$id-1];
        $vater = $person['vater_id'];
        $mutter = $person['mutter_id'];

        if ($vater)
        {
            vorfahren($vater, $generation, $level-1);
        }
        if ($mutter)
        {
            vorfahren($mutter, $generation, $level-1);
        }
    }
    else
    {
        // aktuelle Person
        $person = $personen[$id];
        $level = $generationen;
    }
    echo str_repeat($spacer, $level) . "$person[nachname] $person[vorname] *$person[geburtsdatum]\n<br />";
}

vorfahren($id, $generation, $generationen-1); 
// Ungetestet
Gruss, Miriam.
Ich schmeiß' alles hin und...
... lasse es liegen
Antworten

Zurück zu „Coding & Technik“