ホームページ  >  記事  >  バックエンド開発  >  PHP リファレンスを再理解する

PHP リファレンスを再理解する

不言
不言オリジナル
2018-04-14 14:51:561127ブラウズ

この記事では主に PHP 参照の理解を紹介します。これは、特定の参照価値があります。必要な友人はそれを参照できます。

原因:

日々の開発では、ツリーを構築する必要があります。 id と pid の関係を使用してツリー構造が構築され、ツリーが走査され、他の操作が実行されます。実装方法は2つあります: 1. 再帰、2. 参照
これら 2 つの方法の長所と短所も明らかです。

  1. 再帰は実装が簡単ですが、カウントするデータの量が増えると、パフォーマンスが非常に低下します。

  2. 引用の概念自体は理解しやすく、パフォーマンスも非常に優れていますが、それを使いこなすにはまだ一定の敷居があり、書くのは簡単ではありません。

この記事を書いた理由は、最近とても良い解決策に出会って、引用について改めて理解できたからです。この記事を通じて学習結果をまとめてから、コードに直接進みます。

練習してください

以下のコードを読んで理解できれば、あなたは引用に関して本当に知識があることを意味します。この記事を直接スキップすることもできます。
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;
    }

OK、最初に他のことについては話さないでください。次のデータを使用してこのメ​​ソッドをテストできます。

$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"
              }
            }
          }
        }
      }
    }
  }
}

それでも理解できない場合, それは構いません、一つずつ分析してみましょう
実際には、これを徹底的に理解する必要があります 解決策には2つの部分を理解する必要があります。

  1. foreach代入原則

  2. 引用された原則

foreach
    $data = ["student", "teacher"];
    foreach ($data as $index => $item) {
    }

ループするたびに、$data[0]と$data[1]の「値」がコピーされることに注意してください 1 つのコピーを $item に割り当てます

Quote (必ず自分で試してみてください)
$a = 1;
$b = &$a;
$c = $b;
$c = 2;
猜猜看 $b = ?;

リファレンスについて質問がある場合は、クリックしてください

上記の foreach と Reference を理解できれば、これで完了です。この解決策を理解してください。計画のすべての実行プロセスを理解しました。おめでとうございます。まだ問題がある場合でも、問題はありません。ステップごとに分析しましょう。

分析してください。呼吸を整えて、私の思考の流れに従って、ステップバイステップでいきましょう

    まず、元の関数を見てみましょう
  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;
        }
  2. 変数の状況:
$data。 [0] = ["id" => 1、"pid" => 0、"name" => 'Universe'];

$tmp[1] = &$data[0];
$tree[ ] = &$data[0]

    2 番目のループ
  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 , "name " => '地球']; $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 3 番目のループ
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[2] = ["id" => 3、"pid" => 2、"name" => '中国'];$value = &$data[2]; $tmp[3] = &$data[2];

注:

$temp は $data[1] と同じアドレスを指します したがって、$temp['children' ][] = &$value、操作の結果は次のとおりです:
ここで注意してください:

これは 2 回目のループ中に子に保存された $data[1] への参照です

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

3 回目のループでは、 $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 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;
    }

変数の状況:

$data[3] = ["id" => 3 、"name" => '北京'];$value = &$data[3];$tmp[ 3] = &$data[3];

注:

$temp は &$tmp[2] で、$data[1]と同じアドレスを指します。したがって、$temp['children'][] = &$value、演算の結果は次のとおりです:
こちら 注:

これは、3 番目のサイクル中に子に保存された $data[2] への参照です

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

4 番目のサイクルでは、$data[2][ 'children'][] = &$value、$value は $data[3]
を指しているため、結果は次のようになります。この時点で、実行プロセス全体が完了しました。 :)

ちなみに、別の方法もありますが、これも参考にしません。上記の方法を理解していれば、次の方法は比較的簡単です。
rreee

関連の推奨事項:php

で引用されたいくつかの使用例の要約

以上がPHP リファレンスを再理解するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。