일련의 부모 - 자식 관계를 계층 트리로 변환 하시겠습니까?
PHP일련의 부모 - 자식 관계를 계층 트리로 변환 하시겠습니까?
이름 - 부모 이름 쌍이 많아 가능한 한 많은 계층 구조 트리 구조로 전환하고 싶습니다. 예를 들어, 다음과 같은 쌍이 될 수 있습니다.
Child : Parent
H : G
F : G
G : D
E : D
A : E
B : C
C : E
D : NULL
어느 것이 (a) 계층 적 트리로 변형 될 필요가 있는가?
D
├── E
│ ├── A
│ │ └── B
│ └── C
└── G
├── F
└── H
최종 결과는 중첩 된
- 요소 집합이며 각
- 에는 자식 이름이 들어 있습니다.
쌍 (아이는 자신의 부모, 부모는 아이의 자식 등)에 모순이 없으므로 여러 최적화가 이루어질 수 있습니다.
PHP에서 child => parent 쌍을 포함하는 배열을 중첩 된
- 집합으로 변환하는 방법은 무엇입니까?
-
==============================
1.이것은 자식 구조 / 부모 구조를 트리 구조로 파싱하는 또 다른 재귀 함수를 출력하는 아주 기본적인 재귀 함수를 필요로합니다. 하나의 함수로 충분하지만 여기서는 명확성을 위해 두 가지를 사용합니다 (이 함수의 끝에는 결합 된 함수가 있습니다).
이것은 자식 구조 / 부모 구조를 트리 구조로 파싱하는 또 다른 재귀 함수를 출력하는 아주 기본적인 재귀 함수를 필요로합니다. 하나의 함수로 충분하지만 여기서는 명확성을 위해 두 가지를 사용합니다 (이 함수의 끝에는 결합 된 함수가 있습니다).
먼저 자식 / 부모 쌍의 배열을 초기화합니다.
$tree = array( 'H' => 'G', 'F' => 'G', 'G' => 'D', 'E' => 'D', 'A' => 'E', 'B' => 'C', 'C' => 'E', 'D' => null );
그런 다음 해당 배열을 계층 적 트리 구조로 구문 분석하는 함수는 다음과 같습니다.
function parseTree($tree, $root = null) { $return = array(); # Traverse the tree and search for direct children of the root foreach($tree as $child => $parent) { # A direct child is found if($parent == $root) { # Remove item from tree (we don't need to traverse this again) unset($tree[$child]); # Append the child into result array and parse its children $return[] = array( 'name' => $child, 'children' => parseTree($tree, $child) ); } } return empty($return) ? null : $return; }
정렬되지 않은 목록을 인쇄하기 위해 그 트리를 가로 지르는 함수 :
function printTree($tree) { if(!is_null($tree) && count($tree) > 0) { echo '<ul>'; foreach($tree as $node) { echo '<li>'.$node['name']; printTree($node['children']); echo '</li>'; } echo '</ul>'; } }
실제 사용량 :
$result = parseTree($tree); printTree($result);
$ result의 내용은 다음과 같습니다.
Array( [0] => Array( [name] => D [children] => Array( [0] => Array( [name] => G [children] => Array( [0] => Array( [name] => H [children] => NULL ) [1] => Array( [name] => F [children] => NULL ) ) ) [1] => Array( [name] => E [children] => Array( [0] => Array( [name] => A [children] => NULL ) [1] => Array( [name] => C [children] => Array( [0] => Array( [name] => B [children] => NULL ) ) ) ) ) ) ) )
좀 더 효율성을 원한다면, 그 함수들을 하나로 결합하고 반복 횟수를 줄일 수 있습니다 :
function parseAndPrintTree($root, $tree) { $return = array(); if(!is_null($tree) && count($tree) > 0) { echo '<ul>'; foreach($tree as $child => $parent) { if($parent == $root) { unset($tree[$child]); echo '<li>'.$child; parseAndPrintTree($child, $tree); echo '</li>'; } } echo '</ul>'; } }
이처럼 작은 8 개의 반복 만 데이터 세트에 저장하지만 더 큰 세트에서는 차이를 만들 수 있습니다.
-
==============================
2.트리를 만드는 또 다른 함수 (재귀가 필요없고 대신 참조를 사용함) :
트리를 만드는 또 다른 함수 (재귀가 필요없고 대신 참조를 사용함) :
$array = array('H' => 'G', 'F' => 'G', ..., 'D' => null); function to_tree($array) { $flat = array(); $tree = array(); foreach ($array as $child => $parent) { if (!isset($flat[$child])) { $flat[$child] = array(); } if (!empty($parent)) { $flat[$parent][$child] =& $flat[$child]; } else { $tree[$child] =& $flat[$child]; } } return $tree; }
다음과 같은 계층 적 배열을 반환합니다.
Array( [D] => Array( [G] => Array( [H] => Array() [F] => Array() ) ... ) )
재귀 함수를 사용하여 쉽게 HTML 목록으로 인쇄 할 수 있습니다.
-
==============================
3.$ 트리의 플랫 구조를 계층 구조로 변환하는 또 다른 단순화 된 방법. 노출을 위해서는 하나의 임시 배열 만 필요합니다.
$ 트리의 플랫 구조를 계층 구조로 변환하는 또 다른 단순화 된 방법. 노출을 위해서는 하나의 임시 배열 만 필요합니다.
// add children to parents $flat = array(); # temporary array foreach ($tree as $name => $parent) { $flat[$name]['name'] = $name; # self if (NULL === $parent) { # no parent, is root element, assign it to $tree $tree = &$flat[$name]; } else { # has parent, add self as child $flat[$parent]['children'][] = &$flat[$name]; } } unset($flat);
계층 구조를 다차원 배열로 가져 오는 것은 다음과 같습니다.
Array ( [children] => Array ( [0] => Array ( [children] => Array ( [0] => Array ( [name] => H ) [1] => Array ( [name] => F ) ) [name] => G ) [1] => Array ( [name] => E [children] => Array ( [0] => Array ( [name] => A ) [1] => Array ( [children] => Array ( [0] => Array ( [name] => B ) ) [name] => C ) ) ) ) [name] => D )
재귀를 피하려면 출력이 작습니다 (큰 구조에서는 부담이 될 수 있음).
나는 배열을 출력하기 위해 항상 UL / LI "딜레마"를 풀고 싶었습니다. 딜레마는 각 항목이 어린이가 후속 조치를 취할지 또는 선행 요소를 몇 개 닫아야하는지 여부를 알지 못한다는 것입니다. 또 다른 대답은 이미 RecursiveIteratorIterator를 사용하고 getDepth () 및 기타 작성한 Iterator에서 제공 한 메타 정보를 찾고 해결했습니다. 중첩 된 모델을
- 에 넣되 "닫힌"하위 트리는 숨겨 둡니다. 그 대답은 반복자를 사용하면 매우 유연하다는 것을 보여줍니다.
- 요소에 대해이 문제를 해결하기를 항상 원했습니다.
내가 내놓은 기본 개념은 다음과 같다.
우선 주 출력 로직부터 시작합니다. 이제 계층 적 $ 트리 배열을 사용하면 최종 코드는 다음과 같이 보입니다.
$root = new TreeNode($tree); $it = new TreeNodesIterator(array($root)); $rit = new RecursiveListIterator($it); $decor = new ListDecorator($rit); $rit->addDecorator($decor); foreach($rit as $item) { $inset = $decor->inset(1); printf("%s%s\n", $inset, $item->getName()); }
먼저
- 및
- 요소를 래핑하고 목록 구조가 출력되는 방식을 결정하는 ListDecorator에 대해 살펴 보겠습니다.
class ListDecorator { private $iterator; public function __construct(RecursiveListIterator $iterator) { $this->iterator = $iterator; } public function inset($add = 0) { return str_repeat(' ', $this->iterator->getDepth()*2+$add); }
생성자는 작업중인 iterator를 취합니다. 인셋은 출력을 들여 쓰기하기위한 도우미 함수 일뿐입니다. 나머지는 각 이벤트의 출력 함수입니다.
public function beginElement() { printf("%s<li>\n", $this->inset()); } public function endElement() { printf("%s</li>\n", $this->inset()); } public function beginChildren() { printf("%s<ul>\n", $this->inset(-1)); } public function endChildren() { printf("%s</ul>\n", $this->inset(-1)); } public function beginIteration() { printf("%s<ul>\n", $this->inset()); } public function endIteration() { printf("%s</ul>\n", $this->inset()); } }
이러한 출력 기능을 염두에두고, 이것은 주요 출력 후 처리 / 루프입니다. 단계별로 살펴 보겠습니다.
$root = new TreeNode($tree);
반복을 시작할 때 사용할 루트 TreeNode를 만듭니다.
$it = new TreeNodesIterator(array($root));
이 TreeNodesIterator는, 단일의 $ 루트 노드에 재귀 적 반복을 가능하게하는 RecursiveIterator입니다. 이 클래스는 반복을 위해 무언가가 필요하고 TreeNode 요소의 배열 인 자식 집합과 함께 다시 사용할 수 있으므로 배열로 전달됩니다.
$rit = new RecursiveListIterator($it);
이 RecursiveListIterator는 상기 이벤트를 제공하는 RecursiveIteratorIterator입니다. 이를 사용하려면 ListDecorator 만 제공 (위의 클래스)하고 addDecorator로 할당해야합니다.
$decor = new ListDecorator($rit); $rit->addDecorator($decor);
그러면 모든 것을 설정하고 각 노드를 출력합니다.
foreach($rit as $item) { $inset = $decor->inset(1); printf("%s%s\n", $inset, $item->getName()); }
이 예제에서 보듯이 전체 출력 로직은 ListDecorator 클래스와이 단일 foreach로 캡슐화됩니다. 전체 재귀 적 트래버스는 내부적으로 재귀 함수 호출이 수행되지 않는다는 것을 의미하는 스택 된 프로 시저를 제공하는 SPL 재귀 반복자로 완전히 캡슐화되었습니다.
이벤트 기반 ListDecorator를 사용하면 특별히 출력을 수정하고 동일한 데이터 구조에 대해 여러 유형의 목록을 제공 할 수 있습니다. 배열 데이터가 TreeNode에 캡슐화되어 입력을 변경할 수도 있습니다.
전체 코드 예 :
<?php namespace My; $tree = array('H' => 'G', 'F' => 'G', 'G' => 'D', 'E' => 'D', 'A' => 'E', 'B' => 'C', 'C' => 'E', 'D' => null); // add children to parents $flat = array(); # temporary array foreach ($tree as $name => $parent) { $flat[$name]['name'] = $name; # self if (NULL === $parent) { # no parent, is root element, assign it to $tree $tree = &$flat[$name]; } else { # has parent, add self as child $flat[$parent]['children'][] = &$flat[$name]; } } unset($flat); class TreeNode { protected $data; public function __construct(array $element) { if (!isset($element['name'])) throw new InvalidArgumentException('Element has no name.'); if (isset($element['children']) && !is_array($element['children'])) throw new InvalidArgumentException('Element has invalid children.'); $this->data = $element; } public function getName() { return $this->data['name']; } public function hasChildren() { return isset($this->data['children']) && count($this->data['children']); } /** * @return array of child TreeNode elements */ public function getChildren() { $children = $this->hasChildren() ? $this->data['children'] : array(); $class = get_called_class(); foreach($children as &$element) { $element = new $class($element); } unset($element); return $children; } } class TreeNodesIterator implements \RecursiveIterator { private $nodes; public function __construct(array $nodes) { $this->nodes = new \ArrayIterator($nodes); } public function getInnerIterator() { return $this->nodes; } public function getChildren() { return new TreeNodesIterator($this->nodes->current()->getChildren()); } public function hasChildren() { return $this->nodes->current()->hasChildren(); } public function rewind() { $this->nodes->rewind(); } public function valid() { return $this->nodes->valid(); } public function current() { return $this->nodes->current(); } public function key() { return $this->nodes->key(); } public function next() { return $this->nodes->next(); } } class RecursiveListIterator extends \RecursiveIteratorIterator { private $elements; /** * @var ListDecorator */ private $decorator; public function addDecorator(ListDecorator $decorator) { $this->decorator = $decorator; } public function __construct($iterator, $mode = \RecursiveIteratorIterator::SELF_FIRST, $flags = 0) { parent::__construct($iterator, $mode, $flags); } private function event($name) { // event debug code: printf("--- %'.-20s --- (Depth: %d, Element: %d)\n", $name, $this->getDepth(), @$this->elements[$this->getDepth()]); $callback = array($this->decorator, $name); is_callable($callback) && call_user_func($callback); } public function beginElement() { $this->event('beginElement'); } public function beginChildren() { $this->event('beginChildren'); } public function endChildren() { $this->testEndElement(); $this->event('endChildren'); } private function testEndElement($depthOffset = 0) { $depth = $this->getDepth() + $depthOffset; isset($this->elements[$depth]) || $this->elements[$depth] = 0; $this->elements[$depth] && $this->event('endElement'); } public function nextElement() { $this->testEndElement(); $this->event('{nextElement}'); $this->event('beginElement'); $this->elements[$this->getDepth()] = 1; } public function beginIteration() { $this->event('beginIteration'); } public function endIteration() { $this->testEndElement(); $this->event('endIteration'); } } class ListDecorator { private $iterator; public function __construct(RecursiveListIterator $iterator) { $this->iterator = $iterator; } public function inset($add = 0) { return str_repeat(' ', $this->iterator->getDepth()*2+$add); } public function beginElement() { printf("%s<li>\n", $this->inset(1)); } public function endElement() { printf("%s</li>\n", $this->inset(1)); } public function beginChildren() { printf("%s<ul>\n", $this->inset()); } public function endChildren() { printf("%s</ul>\n", $this->inset()); } public function beginIteration() { printf("%s<ul>\n", $this->inset()); } public function endIteration() { printf("%s</ul>\n", $this->inset()); } } $root = new TreeNode($tree); $it = new TreeNodesIterator(array($root)); $rit = new RecursiveListIterator($it); $decor = new ListDecorator($rit); $rit->addDecorator($decor); foreach($rit as $item) { $inset = $decor->inset(2); printf("%s%s\n", $inset, $item->getName()); }
Outpupt :
<ul> <li> D <ul> <li> G <ul> <li> H </li> <li> F </li> </ul> </li> <li> E <ul> </li> <li> A </li> <li> C <ul> <li> B </li> </ul> </li> </ul> </li> </ul> </li> </ul>
데모 (PHP 5.2 변형)
가능한 변형은 모든 RecursiveIterator를 반복하고 발생할 수있는 모든 이벤트에 대해 반복을 제공하는 반복자입니다. foreach 루프 내부의 스위치 / 케이스가 이벤트를 처리 할 수 있습니다.
관련 항목 :
-
==============================
4.음, 먼저 키 - 값 쌍의 직선 배열을 계층 적 배열로 바꿉니다.
음, 먼저 키 - 값 쌍의 직선 배열을 계층 적 배열로 바꿉니다.
function convertToHeiarchical(array $input) { $parents = array(); $root = array(); $children = array(); foreach ($input as $item) { $parents[$item['id']] = &$item; if ($item['parent_id']) { if (!isset($children[$item['parent_id']])) { $children[$item['parent_id']] = array(); } $children[$item['parent_id']][] = &$item; } else { $root = $item['id']; } } foreach ($parents as $id => &$item) { if (isset($children[$id])) { $item['children'] = $children[$id]; } else { $item['children'] = array(); } } return $parents[$root]; }
그러면 parent_id와 id가있는 평면 배열을 계층 적 배열로 변환 할 수 있습니다.
$item = array( 'id' => 'A', 'blah' => 'blah', 'children' => array( array( 'id' => 'B', 'blah' => 'blah', 'children' => array( array( 'id' => 'C', 'blah' => 'blah', 'children' => array(), ), ), 'id' => 'D', 'blah' => 'blah', 'children' => array( array( 'id' => 'E', 'blah' => 'blah', 'children' => array(), ), ), ), ), );
그런 다음 렌더링 기능을 만듭니다.
function renderItem($item) { $out = "Your OUtput For Each Item Here"; $out .= "<ul>"; foreach ($item['children'] as $child) { $out .= "<li>".renderItem($child)."</li>"; } $out .= "</ul>"; return $out; }
-
==============================
5.Alexander-Konstantinov의 솔루션은 처음에는 읽기가 쉽지 않지만 성능 측면에서는 천재성과 기하 급수적으로 더 뛰어나지 만 최고의 해답으로 선정되었습니다.
Alexander-Konstantinov의 솔루션은 처음에는 읽기가 쉽지 않지만 성능 측면에서는 천재성과 기하 급수적으로 더 뛰어나지 만 최고의 해답으로 선정되었습니다.
감사의 말,이 게시물에 제시된 2 가지 솔루션을 비교하기 위해 벤치 마크를 작성했습니다.
나는 변환해야만했던 6 레벨의 @ 250k 플랫 트리를 가지고 있었고 그렇게하는 더 좋은 방법을 찾고 재귀 반복을 피했습니다.
재귀 대 참조 :
// Generate a 6 level flat tree $root = null; $lvl1 = 13; $lvl2 = 11; $lvl3 = 7; $lvl4 = 5; $lvl5 = 3; $lvl6 = 1; $flatTree = []; for ($i = 1; $i <= 450000; $i++) { if ($i % 3 == 0) { $lvl5 = $i; $flatTree[$lvl6] = $lvl5; continue; } if ($i % 5 == 0) { $lvl4 = $i; $flatTree[$lvl5] = $lvl4; continue; } if ($i % 7 == 0) { $lvl3 = $i; $flatTree[$lvl3] = $lvl2; continue; } if ($i % 11 == 0) { $lvl2 = $i; $flatTree[$lvl2] = $lvl1; continue; } if ($i % 13 == 0) { $lvl1 = $i; $flatTree[$lvl1] = $root; continue; } $lvl6 = $i; } echo 'Array count: ', count($flatTree), PHP_EOL; // Reference function function treeByReference($flatTree) { $flat = []; $tree = []; foreach ($flatTree as $child => $parent) { if (!isset($flat[$child])) { $flat[$child] = []; } if (!empty($parent)) { $flat[$parent][$child] =& $flat[$child]; } else { $tree[$child] =& $flat[$child]; } } return $tree; } // Recursion function function treeByRecursion($flatTree, $root = null) { $return = []; foreach($flatTree as $child => $parent) { if ($parent == $root) { unset($flatTree[$child]); $return[$child] = treeByRecursion($flatTree, $child); } } return $return ?: []; } // Benchmark reference $t1 = microtime(true); $tree = treeByReference($flatTree); echo 'Reference: ', (microtime(true) - $t1), PHP_EOL; // Benchmark recursion $t2 = microtime(true); $tree = treeByRecursion($flatTree); echo 'Recursion: ', (microtime(true) - $t2), PHP_EOL;
출력 자체에 대해 말하고 있습니다 :
Array count: 255493 Reference: 0.3259289264679 (less than 0.4s) Recursion: 6604.9865279198 (almost 2h)
-
==============================
6.UL과 LI를 파싱하려면 다음과 같이됩니다.
UL과 LI를 파싱하려면 다음과 같이됩니다.
$array = array ( 'H' => 'G' 'F' => 'G' 'G' => 'D' 'E' => 'D' 'A' => 'E' 'B' => 'C' 'C' => 'E' 'D' => 'NULL' ); recurse_uls ($array, 'NULL'); function recurse_uls ($array, $parent) { echo '<ul>'; foreach ($array as $c => $p) { if ($p != $parent) continue; echo '<li>'.$c.'</li>'; recurse_uls ($array, $c); } echo '</ul>'; }
하지만 배열을 반복적으로 반복 할 필요가없는 솔루션을보고 싶습니다 ...
-
==============================
7.다음은 내가 생각해 낸 것입니다.
다음은 내가 생각해 낸 것입니다.
$arr = array( 'H' => 'G', 'F' => 'G', 'G' => 'D', 'E' => 'D', 'A' => 'E', 'B' => 'C', 'C' => 'E', 'D' => null ); $nested = parentChild($arr); print_r($nested); function parentChild(&$arr, $parent = false) { if( !$parent) { //initial call $rootKey = array_search( null, $arr); return array($rootKey => parentChild($arr, $rootKey)); }else { // recursing through $keys = array_keys($arr, $parent); $piece = array(); if($keys) { // found children, so handle them if( !is_array($keys) ) { // only one child $piece = parentChild($arr, $keys); }else{ // multiple children foreach( $keys as $key ){ $piece[$key] = parentChild($arr, $key); } } }else { return $parent; //return the main tag (no kids) } return $piece; // return the array built via recursion } }
출력 :
Array ( [D] => Array ( [G] => Array ( [H] => H [F] => F ) [E] => Array ( [A] => A [C] => Array ( [B] => B ) ) ) )
-
==============================
8.동적 트리보기 및 메뉴를 만드는 방법
동적 트리보기 및 메뉴를 만드는 방법
1 단계 : 먼저 우리는 mysql 데이터베이스에 treeview 테이블을 생성합니다. 이 테이블에는 4 개의 column.id가 포함되어 있으며 id는 작업 ID이며 name은 작업 이름입니다.
- -- Table structure for table `treeview_items` -- CREATE TABLE IF NOT EXISTS `treeview_items` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(200) NOT NULL, `title` varchar(200) NOT NULL, `parent_id` varchar(11) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=7 ; -- -- Dumping data for table `treeview_items` -- INSERT INTO `treeview_items` (`id`, `name`, `title`, `parent_id`) VALUES (1, 'task1', 'task1title', '2'), (2, 'task2', 'task2title', '0'), (3, 'task3', 'task1title3', '0'), (4, 'task4', 'task2title4', '3'), (5, 'task4', 'task1title4', '3'), (6, 'task5', 'task2title5', '5');
2 단계 : 트리 뷰 재귀 적 방법 현재 작업 ID가 이전 작업 ID보다 큰 경우 재귀 호출 트리 createTreeView () 메서드를 만들었습니다.
function createTreeView($array, $currentParent, $currLevel = 0, $prevLevel = -1) { foreach ($array as $categoryId => $category) { if ($currentParent == $category['parent_id']) { if ($currLevel > $prevLevel) echo " <ol class='tree'> "; if ($currLevel == $prevLevel) echo " </li> "; echo '<li> <label for="subfolder2">'.$category['name'].'</label> <input type="checkbox" name="subfolder2"/>'; if ($currLevel > $prevLevel) { $prevLevel = $currLevel; } $currLevel++; createTreeView ($array, $categoryId, $currLevel, $prevLevel); $currLevel--; } } if ($currLevel == $prevLevel) echo " </li> </ol> "; }
3 단계 : 트리 뷰를 표시 할 색인 파일을 만듭니다. 이것은 treeview 예제의 주요 파일입니다. 여기서는 필수 매개 변수와 함께 createTreeView () 메소드를 호출합니다.
<body> <link rel="stylesheet" type="text/css" href="_styles.css" media="screen"> <?php mysql_connect('localhost', 'root'); mysql_select_db('test'); $qry="SELECT * FROM treeview_items"; $result=mysql_query($qry); $arrayCategories = array(); while($row = mysql_fetch_assoc($result)){ $arrayCategories[$row['id']] = array("parent_id" => $row['parent_id'], "name" => $row['name']); } ?> <div id="content" class="general-style1"> <?php if(mysql_num_rows($result)!=0) { ?> <?php createTreeView($arrayCategories, 0); ?> <?php } ?> </div> </body>
4 단계 : CSS 파일 style.css 만들기 여기에 우리는 모든 CSS 관련 클래스를 작성합니다. 현재 트리 목록을 작성하는 순서 목록을 사용하고 있습니다. 여기에서 이미지 경로를 변경할 수도 있습니다.
img { border: none; } input, select, textarea, th, td { font-size: 1em; } /* CSS Tree menu styles */ ol.tree { padding: 0 0 0 30px; width: 300px; } li { position: relative; margin-left: -15px; list-style: none; } li.file { margin-left: -1px !important; } li.file a { background: url(document.png) 0 0 no-repeat; color: #fff; padding-left: 21px; text-decoration: none; display: block; } li.file a[href *= '.pdf'] { background: url(document.png) 0 0 no-repeat; } li.file a[href *= '.html'] { background: url(document.png) 0 0 no-repeat; } li.file a[href $= '.css'] { background: url(document.png) 0 0 no-repeat; } li.file a[href $= '.js'] { background: url(document.png) 0 0 no-repeat; } li input { position: absolute; left: 0; margin-left: 0; opacity: 0; z-index: 2; cursor: pointer; height: 1em; width: 1em; top: 0; } li input + ol { background: url(toggle-small-expand.png) 40px 0 no-repeat; margin: -0.938em 0 0 -44px; /* 15px */ height: 1em; } li input + ol > li { display: none; margin-left: -14px !important; padding-left: 1px; } li label { background: url(folder-horizontal.png) 15px 1px no-repeat; cursor: pointer; display: block; padding-left: 37px; } li input:checked + ol { background: url(toggle-small.png) 40px 5px no-repeat; margin: -1.25em 0 0 -44px; /* 20px */ padding: 1.563em 0 0 80px; height: auto; } li input:checked + ol > li { display: block; margin: 0 0 0.125em; /* 2px */} li input:checked + ol > li:last-child { margin: 0 0 0.063em; /* 1px */ }
자세한 내용은
from https://stackoverflow.com/questions/2915748/convert-a-series-of-parent-child-relationships-into-a-hierarchical-tree by cc-by-sa and MIT license
- 요소를 래핑하고 목록 구조가 출력되는 방식을 결정하는 ListDecorator에 대해 살펴 보겠습니다.
그러나 그것은 미리 정렬 된 목록 이었으므로 귀하의 예에 적합하지 않습니다. 또한 표준 트리 구조와 HTML의
- 및
- 요소에 대해이 문제를 해결하기를 항상 원했습니다.
나는 재귀가 관련되어 있다는 느낌을 가지고 있지만, 나는 그것을 완전히 생각할만큼 충분히 깨어 있지 않다.
해결법
-
'PHP' 카테고리의 다른 글
PHP에서 배열의 중복 값을 제거하는 방법 (0) | 2018.09.08 |
---|---|
PHP에서 빈 값으로부터 기본 객체를 생성 하시겠습니까? (0) | 2018.09.08 |
언제 PHP 상수 "PHP_EOL"을 사용합니까? (0) | 2018.09.08 |
PHP를 통해 CSV로 내보내기 (0) | 2018.09.08 |
PHP를 사용한 가장 간단한 양방향 암호화 (0) | 2018.09.08 |