복붙노트

배열 목록에서 배열 트리 만들기

PHP

배열 목록에서 배열 트리 만들기

나는 이런 식으로 목록을 가지고 :

array(
  array(id=>100, parentid=>0, name=>'a'),
  array(id=>101, parentid=>100, name=>'a'),
  array(id=>102, parentid=>101, name=>'a'),
  array(id=>103, parentid=>101, name=>'a'),
)

하지만 더 큰 그래서 나는 이렇게 구조와 같은 나무에 이것을 만드는 효율적인 방법이 필요합니다 :

array(
  id=>100, parentid=>0, name=>'a', children=>array(
    id=>101, parentid=>100, name=>'a', children=>array(
      id=>102, parentid=>101, name=>'a',
      id=>103, parentid=>101, name=>'a',
    )
  )
)

중첩 된 집합이나 내 데이터베이스에 왼쪽 및 오른쪽 값을 추가 할 수있는 것 같은 것들을 사용할 수 없습니다. 어떤 아이디어?

해결법

  1. ==============================

    1.이게 내가 해결 한 방법이야.

    이게 내가 해결 한 방법이야.

    $arr = array(
      array('id'=>100, 'parentid'=>0, 'name'=>'a'),
      array('id'=>101, 'parentid'=>100, 'name'=>'a'),
      array('id'=>102, 'parentid'=>101, 'name'=>'a'),
      array('id'=>103, 'parentid'=>101, 'name'=>'a'),
    );
    
    $new = array();
    foreach ($arr as $a){
        $new[$a['parentid']][] = $a;
    }
    $tree = createTree($new, array($arr[0]));
    print_r($tree);
    
    function createTree(&$list, $parent){
        $tree = array();
        foreach ($parent as $k=>$l){
            if(isset($list[$l['id']])){
                $l['children'] = createTree($list, $list[$l['id']]);
            }
            $tree[] = $l;
        } 
        return $tree;
    }
    
  2. ==============================

    2.1 개 이상의 parentid [0] 요소가 필요하면 작은 수정

    1 개 이상의 parentid [0] 요소가 필요하면 작은 수정

    $arr = array(
      array('id'=>100, 'parentid'=>0, 'name'=>'a'),
      array('id'=>101, 'parentid'=>100, 'name'=>'a'),
      array('id'=>102, 'parentid'=>101, 'name'=>'a'),
      array('id'=>103, 'parentid'=>101, 'name'=>'a'),
    );
    
    $new = array();
    foreach ($arr as $a){
        $new[$a['parentid']][] = $a;
    }
    $tree = createTree($new, $new[0]); // changed
    print_r($tree);
    
    function createTree(&$list, $parent){
        $tree = array();
        foreach ($parent as $k=>$l){
            if(isset($list[$l['id']])){
                $l['children'] = createTree($list, $list[$l['id']]);
            }
            $tree[] = $l;
        } 
        return $tree;
    }
    
  3. ==============================

    3.썬더 스트라이커 (Thunderstriker)의 변종에 대한 한 가지 더 많은 재 작업 - 한 가지 기능의 모든 논리 :

    썬더 스트라이커 (Thunderstriker)의 변종에 대한 한 가지 더 많은 재 작업 - 한 가지 기능의 모든 논리 :

    function buildTree($flat, $pidKey, $idKey = null)
    {
        $grouped = array();
        foreach ($flat as $sub){
            $grouped[$sub[$pidKey]][] = $sub;
        }
    
        $fnBuilder = function($siblings) use (&$fnBuilder, $grouped, $idKey) {
            foreach ($siblings as $k => $sibling) {
                $id = $sibling[$idKey];
                if(isset($grouped[$id])) {
                    $sibling['children'] = $fnBuilder($grouped[$id]);
                }
                $siblings[$k] = $sibling;
            }
    
            return $siblings;
        };
    
        $tree = $fnBuilder($grouped[0]);
    
        return $tree;
    }
    
    // Example:
    $flat = [
        ['id'=>100, 'parentID'=>0, 'name'=>'a'],
        ['id'=>101, 'parentID'=>100, 'name'=>'a'],
        ['id'=>102, 'parentID'=>101, 'name'=>'a'],
        ['id'=>103, 'parentID'=>101, 'name'=>'a'],
    ];
    
    $tree = buildTree($flat, 'parentID', 'id');
    print_r($tree);
    

    운동장 : https://www.tehplayground.com/5V8QSqnmFJ2wcIoj

  4. ==============================

    4.아서의 재 작업에서 내 적응은 다음과 같습니다.

    아서의 재 작업에서 내 적응은 다음과 같습니다.

    /* Recursive branch extrusion */
    function createBranch(&$parents, $children) {
        $tree = array();
        foreach ($children as $child) {
            if (isset($parents[$child['id']])) {
                $child['children'] =
                    $this->createBranch($parents, $parents[$child['id']]);
            }
            $tree[] = $child;
        } 
        return $tree;
    }
    
    /* Initialization */
    function createTree($flat, $root = 0) {
        $parents = array();
        foreach ($flat as $a) {
            $parents[$a['parent']][] = $a;
        }
        return $this->createBranch($parents, $parents[$root]);
    }
    

    용도:

    $tree = createTree($flat);
    
  5. ==============================

    5.나는 재귀적인 대신에 예외적 인 'while-based'를 만들었지 만 고아가 없을 때까지 배열을 따라 다니는 다차원 정렬 함수를 만들었다. 여기 함수 :

    나는 재귀적인 대신에 예외적 인 'while-based'를 만들었지 만 고아가 없을 때까지 배열을 따라 다니는 다차원 정렬 함수를 만들었다. 여기 함수 :

    function treeze( &$a, $parent_key, $children_key )
    {
        $orphans = true; $i;
        while( $orphans )
        {
            $orphans = false;
            foreach( $a as $k=>$v )
            {
                // is there $a[$k] sons?
                $sons = false;
                foreach( $a as $x=>$y )
                if( isset($y[$parent_key]) and $y[$parent_key]!=false and $y[$parent_key]==$k )  
                { 
                    $sons=true; 
                    $orphans=true; 
                    break;
                }
    
                // $a[$k] is a son, without children, so i can move it
                if( !$sons and isset($v[$parent_key]) and $v[$parent_key]!=false )
                {
                    $a[$v[$parent_key]][$children_key][$k] = $v;
                    unset( $a[$k] );
                }
            }
        }
    }
    

    권장 사항 : 배열의 각 요소의 키는 요소 자체의 ID 여야합니다. 예:

    $ARRAY = array(
        1 => array( 'label' => "A" ),
        2 => array( 'label' => "B" ),
        3 => array( 'label' => "C" ),
        4 => array( 'label' => "D" ),
        5 => array( 'label' => "one", 'father' => '1' ),
        6 => array( 'label' => "two", 'father' => '1' ),
        7 => array( 'label' => "three", 'father' => '1' ),
        8 => array( 'label' => "node 1", 'father' => '2' ),
        9 => array( 'label' => "node 2", 'father' => '2' ),
        10 => array( 'label' => "node 3", 'father' => '2' ),
        11 => array( 'label' => "I", 'father' => '9' ),
        12 => array( 'label' => "II", 'father' => '9' ),
        13 => array( 'label' => "III", 'father' => '9' ),
        14 => array( 'label' => "IV", 'father' => '9' ),
        15 => array( 'label' => "V", 'father' => '9' ),
    );
    

    사용법 : 함수는 $ a (배열), $ parent_key (아버지의 id가 저장되는 열의 이름), $ children_key (자식이 이동할 열의 이름)를 필요로합니다. 아무 것도 반환하지 않습니다 (배열은 참조로 변경됩니다). 예:

    treeze( $ARRAY, 'father', 'children' );
    echo "<pre>"; print_r( $ARRAY );
    
  6. ==============================

    6.이를 수행하는 한 가지 방법은 목록의 맨 아래 값을 모두 찾아 새 배열에 추가하는 재귀 함수를 사용하는 것입니다. 그런 다음 각각의 새 ID에 대해 동일한 ID를 가진 함수를 사용하여 반환 된 배열을 가져 와서 해당 항목의 새 하위 배열에 채 웁니다. 마지막으로 새 배열을 반환합니다.

    이를 수행하는 한 가지 방법은 목록의 맨 아래 값을 모두 찾아 새 배열에 추가하는 재귀 함수를 사용하는 것입니다. 그런 다음 각각의 새 ID에 대해 동일한 ID를 가진 함수를 사용하여 반환 된 배열을 가져 와서 해당 항목의 새 하위 배열에 채 웁니다. 마지막으로 새 배열을 반환합니다.

    모든 작업을 수행하지는 않지만 함수의 매개 변수는 다음과 같습니다.

    함수 recursiveChildren ($ items_array, $ parent_id = 0)

    본질적으로, 그것은 부모가 0 인 모든 것을 찾은 다음 그 각각에 대해 그 id를 가진 모든 것들을 부모로 그리고 각각의 것들을 찾아 낼 것입니다.

    최종 결과는 당신이 찾고있는 것이어야합니다.

  7. ==============================

    7.

    //if order by parentid, id
    $arr = array(
        array('id'=>100, 'parentid'=>0, 'name'=>'a'),
        array('id'=>101, 'parentid'=>100, 'name'=>'a'),
        array('id'=>102, 'parentid'=>101, 'name'=>'a'),
        array('id'=>103, 'parentid'=>101, 'name'=>'a'),
    );
    
    $arr_tree = array();
    $arr_tmp = array();
    
    foreach ($arr as $item) {
        $parentid = $item['parentid'];
        $id = $item['id'];
    
        if ($parentid  == 0)
        {
            $arr_tree[$id] = $item;
            $arr_tmp[$id] = &$arr_tree[$id];
        }
        else 
        {
            if (!empty($arr_tmp[$parentid])) 
            {
                $arr_tmp[$parentid]['children'][$id] = $item;
                $arr_tmp[$id] = &$arr_tmp[$parentid]['children'][$id];
            }
        }
    }
    
    unset($arr_tmp);
    echo '<pre>'; print_r($arr_tree); echo "</pre>";
    
  8. ==============================

    8.이 세 가지 패스 방법이 작동하지 않는 이유가 있습니까? 재귀 솔루션의 속도와 속도를 비교하기위한 테스트를 수행하지는 않았지만보다 직선적 인 것으로 보였습니다. 초기 배열이 이미 키인 ID와 연관되어 있으면 첫 번째 foreach ()를 건너 뛸 수 있습니다.

    이 세 가지 패스 방법이 작동하지 않는 이유가 있습니까? 재귀 솔루션의 속도와 속도를 비교하기위한 테스트를 수행하지는 않았지만보다 직선적 인 것으로 보였습니다. 초기 배열이 이미 키인 ID와 연관되어 있으면 첫 번째 foreach ()를 건너 뛸 수 있습니다.

    function array_tree(&$array) {
        $tree = array();
    
        // Create an associative array with each key being the ID of the item
        foreach($array as $k => &$v) {
          $tree[$v['id']] = &$v;
        }
    
        // Loop over the array and add each child to their parent
        foreach($tree as $k => &$v) {
            if(!$v['parent']) {
              continue;
            }
            $tree[$v['parent']]['children'][] = &$v;
        }
    
        // Loop over the array again and remove any items that don't have a parent of 0;
        foreach($tree as $k => &$v) {
          if(!$v['parent']) {
            continue;
          }
          unset($tree[$k]);
        }
    
        return $tree;
    }
    
  9. from https://stackoverflow.com/questions/4196157/create-array-tree-from-array-list by cc-by-sa and MIT license