PHP 참조 다시 이해하기

不言
풀어 주다: 2023-03-23 20:34:01
원래의
1112명이 탐색했습니다.

이 기사는 주로 특정 참조 가치가 있는 PHP 참조에 대한 이해를 소개합니다. 이제 모든 사람과 공유합니다. 도움이 필요한 친구들이 참조할 수 있습니다.

원인:

우리는 일상적인 개발에서 트리를 구성해야 할 필요성에 직면하게 됩니다. .Through id와 pid의 관계를 이용하여 트리 구조를 구축한 후 트리를 순회하며 다른 작업을 수행합니다. 구현하는 방법에는 두 가지가 있습니다: 1. 재귀, 2. 참조
이 두 가지 방법의 장점과 단점도 분명합니다.

  1. 재귀는 구현하기는 쉽지만, 계산하는 데이터의 양이 많아질수록 성능이 매우 저하됩니다.

  2. 인용이라는 개념 자체는 이해하기 쉽고 성능도 매우 좋지만, 잘 활용하기 위해서는 아직 기준점이 있어 쓰기가 쉽지 않습니다.

이 글을 쓰게 된 이유는 요즘 아주 좋은 해결책을 접하고 인용문을 다시 이해하게 되었기 때문입니다. 이 기사를 통해 학습 결과를 요약한 다음 바로 코드로 이동하세요.

Practise

다음 코드를 읽고 이해할 수 있다면 인용에 대한 지식이 풍부하다는 뜻입니다. 이 글을 바로 건너뛰어도 됩니다~.
function buildTreeByReference($data, $id = 'id', $pid = 'pid', $child = "children")
    {
        $tmp = []; //以id为健,$value为值的容器,可以很巧妙的判断根节点元素
        $tree = [];  
        //利用引用,对$data的数据进行操作
        foreach ($data as $key => &$value) {
                // 
                $tmp[$value['id']] = &$value;
                
                if (!isset($tmp[$value['pid']])) {
                    $tree[] = &$tmp[$value['id']];
                }else {
                     $temp = &$tmp[$value['pid']];
                     $temp[$child][] = &$value;
                }
                unset($temp, $value);
        }
        return $tree;
    }
로그인 후 복사

좋아요, 다른 얘기는 먼저 하지 마세요. 다음 데이터로 이 방법을 테스트할 수 있습니다.

$data= [
            ["id" => 1, "pid" => 0 , "name" => 'Universe'],
            ["id" => 2, "pid" => 1 , "name" => 'Earth'],
            ["id" => 3, "pid" => 2 , "name" => 'China'],
            ["id" => 4, "pid" => 3 , "name" => 'Beijing'],
];
로그인 후 복사
추가 참고 사항: 이 방법은 상위 노드가 앞에 있어야 한다는 사실에 주의해야 합니다. 정렬되지 않은 데이터에는 적합하지 않으므로 정렬되지 않은 경우 먼저 정렬해야 합니다.

사고가 없으면 인쇄된 결과는 다음과 같아야 합니다.

array(1) {
  [0]=>
  array(4) {
    ["id"]=>
    int(1)
    ["pid"]=>
    int(0)
    ["name"]=>
    string(8) "Universe"
    ["children"]=>
    array(1) {
      [0]=>
      array(4) {
        ["id"]=>
        int(2)
        ["pid"]=>
        int(1)
        ["name"]=>
        string(5) "Earth"
        ["children"]=>
        array(1) {
          [0]=>
          array(4) {
            ["id"]=>
            int(3)
            ["pid"]=>
            int(2)
            ["name"]=>
            string(5) "China"
            ["children"]=>
            array(1) {
              [0]=>
              array(3) {
                ["id"]=>
                int(4)
                ["pid"]=>
                int(3)
                ["name"]=>
                string(7) "Beijing"
              }
            }
          }
        }
      }
    }
  }
}
로그인 후 복사

아직도 이해가 되지 않는다면 , 상관없으니 하나씩 분석해 보도록 하겠습니다.
사실 이 부분에 대해서는 철저하게 이해해야 합니다. 해결 방법은 두 부분에 대한 이해가 필요합니다.

  1. foreach 할당 원칙

  2. Principle quoted

foreach
    $data = ["student", "teacher"];
    foreach ($data as $index => $item) {
    }
로그인 후 복사

루프할 때마다 $data[0] 및 $data[1]의 "값"이 복사됩니다 $item

Quote에 복사본 하나를 할당하세요(꼭 직접 테스트해 보세요)
$a = 1;
$b = &$a;
$c = $b;
$c = 2;
猜猜看 $b = ?;
로그인 후 복사

참조에 대해 궁금한 점이 있으면 클릭하세요

위의 foreach와 참조를 이해할 수 있다면 여기까지입니다. 이 솔루션을 이해하세요. 계획의 모든 실행 과정을 축하합니다. 잘 배웠습니다. 하지만 여전히 어려움이 있더라도 단계별로 진행해 보세요.

분석

좋아요. 숨을 쉬며 내 생각의 기차를 따라가자.

  1. 먼저 원래 기능을 살펴보자

function buildTreeByReference($data, $id = 'id', $pid = 'pid', $child = "children")
    {
        $tmp = []; #以id为健,$value为值的容器,可以很巧妙的判断根节点元素
        $tree = [];  
        #利用引用,对$data的数据进行操作
        foreach ($data as $key => &$value) {
                
                #&$value取到$data元素对应值的引用
                
                $tmp[$value['id']] = &$value;
                
                #以$value['id']为键,&$value引用为值push到$tmp中,
                #这样可以巧妙的判断当前元素是否为根节点
                
                if (!isset($tmp[$value['pid']])) {
                    #将根节点push到$tree中
                    $tree[] = &$tmp[$value['id']];
                    
                }else {
                     #若当前元素的父节点存在于$tmp中, 引用获取$tmp中对应父节点的值
                     $temp = &$tmp[$value['pid']];
                     #然后将当前元素push到其父节点的children中
                     $temp[$child][] = &$value;
                }
                #为了不引起变量污染, 引用用完后,需要unset掉
                unset($temp, $value);
        }
        return $tree;
    }
로그인 후 복사
  1. 첫 번째 루프

function buildTreeByReference($data, $id = 'id', $pid = 'pid', $child = "children")
    {
       # $tmp = [];
       # $tree = [];  
        
       # foreach ($data as $key => &$value) {
                // 
                $tmp[$value['id']] = &$value;
                
                if (!isset($tmp[$value['pid']])) {
                    $tree[] = &$tmp[$value['id']];
                }else {
        #             $temp = &$tmp[$value['pid']];
        #             $temp[$child][] = &$value;
        #        }
                unset($temp, $value);
        }
        return $tree;
    }
로그인 후 복사

변수 상황:
$data [0] = ["id" => 1, "pid" => 0 , "이름" => '유니버스'];
$tmp[1] = &$data[0];
$tree[ ] = &$data[0]

  1. 두 번째 루프

function buildTreeByReference($data, $id = 'id', $pid = 'pid', $child = "children")
    {
       # $tmp = [];
       # $tree = [];  
        
       # foreach ($data as $key => &$value) {
                // 
                $tmp[$value['id']] = &$value;
                
        #        if (!isset($tmp[$value['pid']])) {
        #            $tree[] = &$tmp[$value['id']];
                }else {
                     $temp = &$tmp[$value['pid']];
                     $temp[$child][] = &$value;
                }
                unset($temp, $value);
        }
        return $tree;
    }
로그인 후 복사
로그인 후 복사
로그인 후 복사

변수 상황:
$data[1] = ["id" => 2, "pid" => 1 " => '지구'];
$value=&$data[1];
$tmp[2] = &$data[1];
참고:
$temp는 &$tmp[1]입니다. $data[0] 주소와 동일한 지점을 가리킵니다.
그래서 $temp['children'][] = &$value, 작업 결과는 다음과 같습니다.

$data[
    [  
     "id" => 1,
     "pid" => 0 ,
     "name" => 'Universe'
     "children"=>[
                 &$data[1],   //注意:存储的是引用
         ]
     ]   
     ...
]
로그인 후 복사
로그인 후 복사

4 세 번째 루프

function buildTreeByReference($data, $id = 'id', $pid = 'pid', $child = "children")
    {
       # $tmp = [];
       # $tree = [];  
        
       # foreach ($data as $key => &$value) {
                // 
                $tmp[$value['id']] = &$value;
                
        #        if (!isset($tmp[$value['pid']])) {
        #            $tree[] = &$tmp[$value['id']];
                }else {
                     $temp = &$tmp[$value['pid']];
                     $temp[$child][] = &$value;
                }
                unset($temp, $value);
        }
        return $tree;
    }
로그인 후 복사
로그인 후 복사
로그인 후 복사

Variable. 상황:
$data[2] = ["id" => 3, "pid" => '중국'];
$value = &$data[2];
$tmp[3] = &$data[2]
참고:
$temp는 &$tmp[2]이며 $data[1]

와 동일한 주소를 가리킵니다. $temp['children' ][] = &$value, 작업 결과는 다음과 같습니다.
참고 사항:
이것은 두 번째 루프 동안 하위 항목에 저장된 $data[1]에 대한 참조입니다

$data[
    [  
     "id" => 1,
     "pid" => 0 ,
     "name" => 'Universe'
     "children"=>[
                 &$data[1],   //注意:存储的是引用
         ]
     ]   
     ...
]
로그인 후 복사
로그인 후 복사

세 번째 루프되면 $data[1]['children'][] = &$value이고 $value는 $data[2]
를 가리키므로 결과는 다음과 같습니다.

   $data[
        [  
         "id" => 1,
         "pid" => 0 ,
         "name" => 'Universe'
         "children"=>[
                       // &$data[1],   //注意:存储的是引用
                         [
                           "id" => 2, 
                           "pid" => 1 ,
                           "name" => 'Earth'
                           "children" => [
                                   &data[2] //注意:存储的是引用   
                            ]
                         
                         ] 
                         
                     ]
             ]
         ]   
         ...
    ]
로그인 후 복사
로그인 후 복사

5 네 번째 루프

function buildTreeByReference($data, $id = 'id', $pid = 'pid', $child = "children")
    {
       # $tmp = [];
       # $tree = [];  
        
       # foreach ($data as $key => &$value) {
                // 
                $tmp[$value['id']] = &$value;
                
        #        if (!isset($tmp[$value['pid']])) {
        #            $tree[] = &$tmp[$value['id']];
                }else {
                     $temp = &$tmp[$value['pid']];
                     $temp[$child][] = &$value;
                }
                unset($temp, $value);
        }
        return $tree;
    }
로그인 후 복사
로그인 후 복사
로그인 후 복사

변수 상황:
$data[3] = ["id" => 4, "pid" => 'Beijing'];
$value = &$data[3];
$tmp [3] = &$data[3];
참고:
$temp는 &$tmp[2]이며 $data[1]

그래서 $temp['children'][과 동일한 주소를 가리킵니다. ] = &$value, 연산 결과는 다음과 같습니다.
여기 참고:
이것은 세 번째 주기 동안 하위 항목에 저장된 $data[2]에 대한 참조입니다.

   $data[
        [  
         "id" => 1,
         "pid" => 0 ,
         "name" => 'Universe'
         "children"=>[
                       // &$data[1],   //注意:存储的是引用
                         [
                           "id" => 2, 
                           "pid" => 1 ,
                           "name" => 'Earth'
                           "children" => [
                                   &data[2] //注意:存储的是引用   
                            ]
                         
                         ] 
                         
                     ]
             ]
         ]   
         ...
    ]
로그인 후 복사
로그인 후 복사

네 번째 주기에서는 $data[2]입니다. ['children'][] = &$value, $value는 $data[3]
을 가리키므로 결과는

   $data[
        [  
         "id" => 1,
         "pid" => 0 ,
         "name" => 'Universe'
         "children"=>[
                       // &$data[1],   //注意:存储的是引用
                         [
                           "id" => 2, 
                           "pid" => 1 ,
                           "name" => 'Earth'
                           "children" => [
                                  // &data[2] //注意:存储的是引用 
                                  [
                                      "id" => 3,
                                      "pid" => 2 ,
                                      "name" => 'China' 
                                      "children" =>[
                                                 &$data[3];  //注意:存储的是引用                            
                                      ]
                                  ]  
                            ]
                         
                         ] 
                         
                     ]
             ]
         ]   
         ...
    ]
로그인 후 복사

ok입니다. 이제 전체 실행 프로세스가 완료되었습니다. :)

그나저나 또 다른 방법이 있는데 이것도 참고해서 분석하지는 않겠습니다. 위 방법을 이해하시면 다음 방법은 비교적 간단합니다.

    public static function buildTreeByReference1($data, $id = 'id', $pid = 'pid', $child = "children")
    {
        $tmp = [];
        
        foreach ($data as $key => $value) {
            $tmp[$value[$id]] = $value;
        }
        $tree = [];
        foreach ($tmp as $key => $value) {
                if (isset($tmp[$value['pid']])) {
                    $tmp[$value['pid']]['children'][] = &$tmp[$key];
                }else{
                    $tree[] = &$tmp[$key];    
                }
        }
        return $tree;
    }
로그인 후 복사

관련 권장사항:

php에서 인용한 여러 사용 사례 요약                                                                                              

위 내용은 PHP 참조 다시 이해하기의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿