Erhalten eines modifizierten Vorbestellungsbaum-Durchlaufmodells (verschachtelter Satz) in a

Lesezeit: 13 Minuten

Erhalten eines modifizierten Vorbestellungsbaum Durchlaufmodells verschachtelter Satz in a
Schleifer

Ich versuche, meine Daten, die hierarchisch mit einem Baumtraversalmodell aufgebaut sind, in ein

    zu bekommen, um sie auf meiner Website anzuzeigen.

    Hier ist mein Code:

    function getCats($) {
      // retrieve all children of $parent
      $query = "SELECT max(rght) as max from t_categories";
      $row = C_DB::fetchSingleRow($query);
      $max = $row["max"];
      $result ="<ul>";
      $query = "SELECT * from t_categories where lft >=0 and rght <= $max";
      if($rs = C_DB::fetchRecordset($query)){
        $p_right ="";
        $p_left ="";
        $p_diff="";          
        while($row = C_DB::fetchRow($rs)){
          $diff = $row["rght"] -$row["lft"];
    
          if($diff == $p_diff){
            $result.= "<li>".$row['title']."</li>";
          }elseif (($row["rght"] - $row["lft"] > 1) && ($row["rght"] > $p_right)){
            $result. "<ul>";
            $result.= "<li>".$row['title']."</li>";
    
          }else{
            $result.= "<li>".$row['title']."</li>";
          } 
    
          $p_right = $row["rght"];
          $p_left = $row["lft"];
          $p_diff = $diff;
        }
      }
      $result.= "</ul>";
      return $result;
    } 
    

    Hier ist meine Beispieltabelle:

    |ID  |  TITLE | lft| rght |
    |1   | Cat 1  | 1      |    16       |
    |18  | Cat 2  | 3      |    4       |
    |22  | Cat 3  | 5      |    6       |
    |28  | Cat 4  | 7      |    8       |
    |34  | Cat 5  | 9      |    9       |
    |46  | Cat 6  | 11      |    10       |
    |47  | Cat 7  | 13      |    12       |
    |49  | Cat 8  | 15      |    14       | 
    

    Jetzt gibt es etwas aus wie:

        <ul>
    <li>Cat 1</li>
    <li>Cat 2</li>
    <li>Cat 3</li>
    <li>Cat 4</li>
    <li>Cat 5</li>
    <li>Cat 6</li>
    <li>Cat 7</li>
    <li>Cat 8</li>
    </ul>
    

    Kann mir jemand sagen, warum oder wie die Liste in einer hierarchischen Struktur ausgegeben wird?

    Verwandtes Thema

  • Sind Ihre Spalten benannt links und rechtsoder lft und right? Und spiegelt Ihr Code wider, was Sie tatsächlich haben?

    – Hobbs

    21. August 09 um 8:21 Uhr

  • Entschuldigung, es wurde behoben. Ich musste meinen Code aus dem Niederländischen übersetzen 😉

    – Schleifer

    21. August 09 um 8:29 Uhr

  • out of topic: Aus vielen Gründen empfehle ich Ihnen, Ihren Code nur auf Englisch zu schreiben. Das ist eine gute Angewohnheit!

    – Irukandji

    21. August 09 um 8:49 Uhr

  • könntest du genau posten was die ausgabe ist sollen für diese Daten sein?

    – Kipp

    24. August 09 um 21:39 Uhr

  • Übrigens, das verschachtelte Set aus Ihrem Beispiel ist kaputt – Sie haben eine fehlende ‘2’ und die doppelte 9 auf Cat 5 macht genauso wenig Sinn wie die lft, die auf Cat 6 bis 8 größer als rechts ist …

    – Henrik Opel

    25. August 2009 um 20:23 Uhr

1643935926 60 Erhalten eines modifizierten Vorbestellungsbaum Durchlaufmodells verschachtelter Satz in a
Henrik Opel

Ok, machen wir ein bisschen Kopfgeldjagd 😉

Schritt 0 – Beispiel zur Desinfektion:

Wie bereits erwähnt, sind Ihre Beispieldaten fehlerhaft, da sie keine gültige verschachtelte Menge definieren. Wenn Sie diese Daten aus einer App übernommen haben, sollten Sie die Einfüge-/Löschlogik überprüfen.

Also habe ich zum Testen eine bereinigte Version wie folgt verwendet:
(MySQL hier, da es als erstes zur Hand war)

CREATE TABLE t_categories`(
  `id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
  `title` VARCHAR(45) NOT NULL,
  `lft` INTEGER UNSIGNED NOT NULL,
  `rght` INTEGER UNSIGNED NOT NULL,
  PRIMARY KEY (`id`)
);

INSERT INTO t_categories (title, lft, rght) VALUES ('Cat 1',1,16);
INSERT INTO t_categories (title, lft, rght) VALUES ('Cat 2',2,3);
INSERT INTO t_categories (title, lft, rght) VALUES ('Cat 3',4,7);
INSERT INTO t_categories (title, lft, rght) VALUES ('Cat 4',5,6);
INSERT INTO t_categories (title, lft, rght) VALUES ('Cat 5',8,13);
INSERT INTO t_categories (title, lft, rght) VALUES ('Cat 6',9,12);
INSERT INTO t_categories (title, lft, rght) VALUES ('Cat 7',10,11);
INSERT INTO t_categories (title, lft, rght) VALUES ('Cat 8',14,15);

Schritt 1 – Lassen Sie die Datenbank die Bestellung vornehmen

Verschachtelte Mengen wurden in erster Linie als bequeme Möglichkeit zum Speichern von Bäumen in Datenbanken erfunden, da sie es ziemlich einfach machen, nach Teilbäumen, übergeordneten Beziehungen und, in diesem Fall besonders interessant, nach Reihenfolge und Tiefe abzufragen:

SELECT node.title, (COUNT(parent.title) - 1) AS depth
 FROM t_categories AS node
 CROSS JOIN t_categories AS parent
 WHERE node.lft BETWEEN parent.lft AND parent.rght
 GROUP BY node.title
 ORDER BY node.lft

Dadurch wird Ihr Set ordentlich geordnet zurückgegeben, beginnend mit dem Stammknoten und bis zum Ende in Vorbestellung. Am wichtigsten ist, dass die Tiefe jedes Knotens als positive Ganzzahl hinzugefügt wird, die angibt, wie viele Ebenen sich der Knoten unter der Wurzel befindet (Ebene 0). Für die obigen Beispieldaten lautet das Ergebnis:

title, depth
'Cat 1', 0
'Cat 2', 1
'Cat 3', 1
'Cat 4', 2
'Cat 5', 1
'Cat 6', 2
'Cat 7', 3
'Cat 8', 1

In Code:

// Grab ordered data
$query = '';
$query .= 'SELECT node.title, (COUNT(parent.title) - 1) AS depth';
$query .= ' FROM t_categories AS node';
$query .= ' CROSS JOIN t_categories AS parent';
$query .= ' WHERE node.lft BETWEEN parent.lft AND parent.rght';
$query .= ' GROUP BY node.title';
$query .= ' ORDER BY node.lft';

$result = mysql_query($query);

// Build array
$tree = array();
while ($row = mysql_fetch_assoc($result)) {
  $tree[] = $row;
}

Das resultierende Array sieht folgendermaßen aus:

Array
(
    [0] => Array
        (
            Getting a modified preorder tree traversal model (nested set) into a 
    => Cat 1 [depth] => 0 ) [1] => Array ( Getting a modified preorder tree traversal model (nested set) into a
      => Cat 2 [depth] => 1 ) ... )

Schritt 2 – Ausgabe als HTML-Listenfragment:

While-Schleife verwenden:

// bootstrap loop
$result="";
$currDepth = -1;  // -1 to get the outer <ul>
while (!empty($tree)) {
  $currNode = array_shift($tree);
  // Level down?
  if ($currNode['depth'] > $currDepth) {
    // Yes, open <ul>
    $result .= '<ul>';
  }
  // Level up?
  if ($currNode['depth'] < $currDepth) {
    // Yes, close n open <ul>
    $result .= str_repeat('</ul>', $currDepth - $currNode['depth']);
  }
  // Always add node
  $result .= '<li>' . $currNode['title'] . '</li>';
  // Adjust current depth
  $currDepth = $currNode['depth'];
  // Are we finished?
  if (empty($tree)) {
    // Yes, close n open <ul>
    $result .= str_repeat('</ul>', $currDepth + 1);
  }
}

print $result;

Gleiche Logik wie rekursive Funktion:

function renderTree($tree, $currDepth = -1) {
  $currNode = array_shift($tree);
  $result="";
  // Going down?
  if ($currNode['depth'] > $currDepth) {
    // Yes, prepend <ul>
    $result .= '<ul>';
  }
  // Going up?
  if ($currNode['depth'] < $currDepth) {
    // Yes, close n open <ul>
    $result .= str_repeat('</ul>', $currDepth - $currNode['depth']);
  }
  // Always add the node
  $result .= '<li>' . $currNode['title'] . '</li>';
  // Anything left?
  if (!empty($tree)) {
    // Yes, recurse
    $result .=  renderTree($tree, $currNode['depth']);
  }
  else {
    // No, close remaining <ul>
    $result .= str_repeat('</ul>', $currNode['depth'] + 1);
  }
  return $result;
}

print renderTree($tree);

Beide geben die folgende Struktur aus:

<ul>
    <li>Cat 1</li>
    <li>
        <ul>
            <li>Cat 2</li>
            <li>Cat 3</li>
            <li>
                <ul>
                    <li>Cat 4</li>
                </ul>
            </li>
            <li>Cat 5</li>
            <li>
                <ul>
                    <li>Cat 6</li>
                    <li>
                        <ul>
                            <li>Cat 7</li>
                        </ul>
                    </li>
                </ul>
            </li>
            <li>Cat 8</li>
        </ul>
    </li>
</ul>

Nitpickers-Ecke: Fragesteller ausdrücklich darum gebeten <ul>aber bestellt ungeordnete Listen!? Komm schon…
😉

  • Gibt es eine ähnliche Funktion, um die Daten in ein verschachteltes Array zu legen?

    – Alex L

    24. September 2009 um 19:42 Uhr

  • @Alex L: Sicher, aber es würde davon abhängen, wie Sie die Verschachtelung durchführen möchten. Sie würden im Grunde die gleiche Logik wie für die Listengenerierung verwenden, aber Sie müssten eine „Verfolgung“ der aktuellen Eltern-/Kind-Kette hinzufügen, um die „Rückverfolgung“ zu einem übergeordneten Array zu ermöglichen, da Sie nicht einfach „ schließen Sie es wie die verschachtelten ul-Tags.

    – Henrik Opel

    18. Oktober ’09 um 20:00 Uhr

  • Haben Sie herausgefunden, wie Sie Arrays aus dieser Ergebnismenge erstellen? Ich weiß, dass ich ein „Tracking“ hinzufügen muss, aber wie? Ich habe diese Frage erweitert: stackoverflow.com/questions/3668702/…

    – Keyne Viana

    08.09.10 um 23:00 Uhr


  • @Henrik Opel. Ich habe Ihre rekursive Funktion getestet und sie funktioniert nicht gut … Unterbaum (UL) muss innerhalb des Tags

  • sein. nicht außerhalb davon … in Ihrem Code “$result .= ‘
  • ‘ . $currNode[‘title’] . ‘
  • ‘”

  • -Tag wird dort geschlossen, wo es geöffnet wurde.

    Benutzer474470

    25. Juni 12 um 9:31 Uhr

  • Wie soll ich es dynamisch einfügen? Siehe meine Frage: stackoverflow.com/questions/11716731/…

    – JKA

    30. Juli 12 um 14:36 ​​Uhr

  • 1643935927 401 Erhalten eines modifizierten Vorbestellungsbaum Durchlaufmodells verschachtelter Satz in a
    zugeben

    Bessere Render-Baum-Funktion das hat bei mir funktioniert (php-Funktion zum Vorbereiten der HTML-Quelle für die Verwendung im jsTree jQuery-Plugin) anstelle des von Henrik Opel:

    function MyRenderTree ( $tree = array(array('name'=>'','depth'=>'')) ){
    
    $current_depth = 0;
    $counter = 0;
    
    $result="<ul>";
    
    foreach($tree as $node){
        $node_depth = $node['depth'];
        $node_name = $node['name'];
        $node_id = $node['category_id'];
    
        if($node_depth == $current_depth){
            if($counter > 0) $result .= '</li>';            
        }
        elseif($node_depth > $current_depth){
            $result .= '<ul>';
            $current_depth = $current_depth + ($node_depth - $current_depth);
        }
        elseif($node_depth < $current_depth){
            $result .= str_repeat('</li></ul>',$current_depth - $node_depth).'</li>';
            $current_depth = $current_depth - ($current_depth - $node_depth);
        }
        $result .= '<li id="c'.$node_id.'"';
        $result .= $node_depth < 2 ?' class="open"':'';
        $result .= '><a href="#"><ins>&nbsp;</ins>'.$node_name.'</a>';
        ++$counter;
    }
     $result .= str_repeat('</li></ul>',$node_depth).'</li>';
    
    $result .= '</ul>';
    
    return $result;}
    

    Ergebnis-HTML:

    <ul>
        <li id="c1" class="open"><a href="#"><ins>&nbsp;</ins>ELECTRONICS</a>
            <ul>
                <li id="c2" class="open"><a href="#"><ins>&nbsp;</ins>TELEVISIONS</a>
                    <ul>
                        <li id="c3"><a href="#"><ins>&nbsp;</ins>TUBE</a></li>
                        <li id="c4"><a href="#"><ins>&nbsp;</ins>LCD</a></li>
                        <li id="c5"><a href="#"><ins>&nbsp;</ins>PLASMA</a>
                            <ul>
                                <li id="c14"><a href="#"><ins>&nbsp;</ins>PLASMA1</a></li>
                                <li id="c15"><a href="#"><ins>&nbsp;</ins>PLASMA2</a></li>
                            </ul>
                        </li>
                    </ul>
                </li>
                <li id="c6" class="open"><a href="#"><ins>&nbsp;</ins>PORTABLE ELECTRONICS</a>
                    <ul>
                        <li id="c7"><a href="#"><ins>&nbsp;</ins>MP3 PLAYERS</a>
                            <ul>
                                <li id="c8"><a href="#"><ins>&nbsp;</ins>FLASH</a></li>
                            </ul>
                        </li>
                        <li id="c9"><a href="#"><ins>&nbsp;</ins>CD PLAYERS</a></li>
                        <li id="c10"><a href="#"><ins>&nbsp;</ins>2 WAY RADIOS</a></li>
                    </ul>
                </li>
            </ul>
        </li>
    </ul>
    

    • Ich bevorzuge diese Antwort, da sie das W3C-Wiki auf Listen respektiert. Quelle: stackoverflow.com/questions/5899337/…

      – tampe125

      8. August 14 um 9:34 Uhr

    • Könnte umgeschrieben werden, um eine rekursive Funktion zu verwenden. Diese Lösung könnte jedoch schneller sein.

      – Jan Vorisek

      31. August 17 um 22:45 Uhr

    1643935927 895 Erhalten eines modifizierten Vorbestellungsbaum Durchlaufmodells verschachtelter Satz in a
    VolkerK

    Es gibt ein PEAR-Paket für den Umgang mit verschachtelten Sätzen: DB_NestedSet.
    Der Artikel könnte Sie auch interessieren Verwalten hierarchischer Daten in MySQL.

    Erhalten eines modifizierten Vorbestellungsbaum Durchlaufmodells verschachtelter Satz in a
    Alix Axel

    Das sollte das sein, wonach Sie suchen:

    function getCats($left = null, $right = null)
    {
        $sql = array();
        $result = null;
    
        if (isset($left) === true)
        {
            $sql[] = 'lft >= ' . intval($left);
        }
    
        if (isset($right) === true)
        {
            $sql[] = 'rght <= ' . intval($right);
        }
    
        if (empty($sql) === true)
        {
            $sql[] = 'lft = 1';
        }
    
        $sql="SELECT * FROM t_categories WHERE " . implode(' AND ', $sql) . ';';
    
        if ($rs = C_DB::fetchRecordset($sql))
        {
            // you need to make sure that the query returns
            // something to correctly display the ULs
            if (empty($rs) === false)
            {
                $result .= '<ul>' . "n";
    
                while ($row = C_DB::fetchRow($rs))
                {
                    $result .= '<li>' . $row['title'] . '</li>' . "n";
                    $result .= getCats($row['lft'], $row['rght']);
                }
    
                $result .= '</ul>' . "n";
            }
        }
    
        return $result;
    }
    

    Um den HTML-Code für Ihren verschachtelten Baum zu erhalten, sollten Sie Folgendes tun:

    echo getCats();
    

    Bitte beachten Sie, dass Ihr verschachteltes Set-Beispiel nicht richtig aussieht. Außerdem sollten Sie sicherstellen, dass ich beim Aufrufen Ihrer C_DB-Klasse keinen Fehler gemacht habe. Ich weiß es nicht, da ich nicht damit vertraut bin.

    1643935928 921 Erhalten eines modifizierten Vorbestellungsbaum Durchlaufmodells verschachtelter Satz in a
    Farbfernseher

    Schleifen Sie einfach durch das Ergebnis:

    $sql = "SELECT node.name, (COUNT(parent.name) - 1) AS depth
            FROM nested_category AS node,
            nested_category AS parent
            WHERE node.lft BETWEEN parent.lft AND parent.rgt
            GROUP BY node.name
            ORDER BY node.lft";
    
    $query_result = mysql_query($sql)
    
    $result = "<ul>";
    $currDepth = 0;
    
    while($row = mysql_fetch_assoc($query_result))
    {
      if($row['depth'] > $currDepth)
      {
        $result .= "<li><ul>"; // open sub tree if level up
      }
    
      if($row['depth'] < $currDepth)
      {
        $result .= str_repeat("</ul></li>", $currDepth - $row['depth']); // close sub tree if level down
      }
    
      $result .= "<li>$row['name']</li>"; // Always add node
      $currDepth = $row['depth'];
    }
    $result .= "</ul>";
    
    echo $result;
    

    1643935928 834 Erhalten eines modifizierten Vorbestellungsbaum Durchlaufmodells verschachtelter Satz in a
    Ram Miranda

    $linaje="";
        $lastnode="";
        $sides['izq']=array();
        $sides['der']=array();
        $print="<ul>"; 
        foreach ($array as $key1 => $value1){ //Proyectos
    
            if(strpos($info[$key1]['linaje'],'-') !== false)
                $compare = strstr($info[$key1]['linaje'],'-',true);
            else
                $compare  = $info[$key1]['linaje'];
    
            if($linaje != ''){
                if ($linaje !=   $compare){
                    $linaje= $compare;
                    $sides['izq']=array();
                    $sides['der']=array();
                    //for($i=1;$i <= substr_count($lastnode,'`')-substr_count($value1,'`');$i++)
                        //$print .= '</ul></li>';
                }
            }
    
    
            if ($lastnode != '')
                for($i=1;$i<= substr_count($lastnode,'`')-substr_count($value1,'`');$i++)
                    $print .= '</ul></li>'; 
    
            if (count($sides['der'])>0)
                if  ($sides['der'][count($sides['der'])-1] > $info[$key1]['der'])
                    $print .= '<ul>';
    
            $print .= '<li><a href="#'.$info[$key1]['id'].'#'.$info[$key1]['linaje'].'">'.substr($value1,substr_count($value1,'`')).'</a>';
    
            if  ($info[$key1]['der'] - $info[$key1]['izq'] == 1)
                    $print .= '</li>';
    
            if ($key1 == count($info)-1)
                for($i=1;$i <= substr_count($lastnode,'`')-1;$i++)
                    $print .= '</ul></li>';
    
            $sides['der'][] = $info[$key1]['der'];
            $sides['izq'][] = $info[$key1]['izq'];
    
            if ($linaje =='')
                    $linaje = $info[$key1]['linaje'];
    
            $lastnode = $value1;
        }
        $print .= '</ul>';
        echo $print;
    

    Der Unterschied besteht darin, dass Sie X Bäume rendern können, dies gilt für eines meiner Projekte. und ich verwende ein Zeichen als Tiefenreferenz, wenn ich die Zeilen aus der DB abrufe

    1643935928 857 Erhalten eines modifizierten Vorbestellungsbaum Durchlaufmodells verschachtelter Satz in a
    Alessandro Minoccheri

    Ich verwende die CROSS JOIN-Abfrage, die das jsTree-jQuery-Menü anzeigt. Alles funktioniert einfach super! Der bestehenden Tabelle habe ich eine Spalte für die Position hinzugefügt. Wenn ich jedoch die Position definiere und alle nach Position bestelle, werden die entsprechenden Elemente nicht richtig gruppiert. Ich denke, es ist ein Abfrageproblem, habe viele Kombinationen ausprobiert, aber keinen Erfolg.

    .

    762370cookie-checkErhalten eines modifizierten Vorbestellungsbaum-Durchlaufmodells (verschachtelter Satz) in a

    This website is using cookies to improve the user-friendliness. You agree by using the website further.

    Privacy policy