PHP usort用于字符串层次结构 [英] PHP usort for string hierarchy

查看:100
本文介绍了PHP usort用于字符串层次结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个具有字符串层次结构的数组,如下所示:

I have a array with a string hierarchy like so:

table, parent_table
test, NULL
test, NULL
test2, test
test4, NULL
test5, test3
test6, test5
test3, test

我想使用类似这样的函数进行排序:

I want to sort with a function that goes something like this:

usort($array, function($a,$b) {
    return ($a['table'] === $b['parent_table']) ? -1 : 1;
});

理想的结果是

table, parent_table
test, NULL
test, NULL
test2, test
test3, test
test5, test3
test6, test5
test4, NULL

这将在孩子表上方对父母进行排序.我一直在努力寻找解决这个问题的好方法.字符串层次结构是否有usort?

This would sort parents above children tables. I've been trying to find a good solution for this problem. Is there a usort for string hierarchies?

推荐答案

<?php

$data = [
    [
        'table' => 'test',
        'parent_table' => NULL,
    ],
    [
        'table' => 'test',
        'parent_table' => NULL,
    ],
    [
        'table' => 'test2',
        'parent_table' => 'test',
    ],
    [
        'table' => 'test4',
        'parent_table' => NULL,
    ],
    [
        'table' => 'test5',
        'parent_table' => 'test3',
    ],
    [
        'table' => 'test6',
        'parent_table' => 'test5',
    ],
    [
        'table' => 'test3',
        'parent_table' => 'test',
    ],
];


function reorderHierarchy($data){

    $hierarchy = [];
    $top_level_parents = [];

    foreach($data as $each_data){
        $hierarchy[$each_data['table']] = array();
        if(is_null($each_data['parent_table'])){
            if(!isset($top_level_parents[$each_data['table']])){
                $top_level_parents[$each_data['table']] = 0;
            }
            $top_level_parents[$each_data['table']]++;
        }
    }

    foreach($data as $each_data){
        if(!is_null($each_data['parent_table'])){
            $hierarchy[$each_data['parent_table']][] = $each_data['table'];
        }
    }

    $result = [];
    traverseHierarchy($hierarchy,$top_level_parents,$result);
    return $result;
}

function traverseHierarchy($hierarchy,$top_level_parents,&$result){
    foreach($top_level_parents as $each_parent => $occurrences){
        while($occurrences-- > 0){
            $result[] = [
                'table' => $each_parent,
                'parent_table' => NULL
            ];
        }       

        traverseChildren($hierarchy,$each_parent,$result);
    }
}

function traverseChildren($hierarchy,$parent,&$result){
    foreach($hierarchy[$parent] as $each_child){
        $result[] = [
            'table' => $each_child,
            'parent_table' => $parent
        ];

        traverseChildren($hierarchy,$each_child,$result);
    }
}


foreach(reorderHierarchy($data) as $each_data){
    echo $each_data['table']," , ",(is_null($each_data['parent_table']) ? "NULL" : $each_data['parent_table']),"<br/>";
}

输出:

test , NULL
test , NULL
test2 , test
test3 , test
test5 , test3
test6 , test5
test4 , NULL

演示: https://3v4l.org/AmJpY

说明:

第1部分:

function reorderHierarchy($data){

    $hierarchy = [];
    $top_level_parents = [];

    foreach($data as $each_data){
        $hierarchy[$each_data['table']] = array();
        if(is_null($each_data['parent_table'])){
            if(!isset($top_level_parents[$each_data['table']])){
                $top_level_parents[$each_data['table']] = 0;
            }
            $top_level_parents[$each_data['table']]++;
        }
    }

    foreach($data as $each_data){
        if(!is_null($each_data['parent_table'])){
            $hierarchy[$each_data['parent_table']][] = $each_data['table'];
        }
    }

    $result = [];
    traverseHierarchy($hierarchy,$top_level_parents,$result);
    return $result;
}

  • 在上面的函数中,我们创建2种数组,分别为$hierarchy$top_level_parents. $hierarchy是一个数组,其中每个键内部都有子键. $top_level_parents是一个数组,该数组收集所有没有父项的表,其键为表名,值为值.

    • In the above function, we are creating 2 kinds of arrays, namely, $hierarchy and $top_level_parents. $hierarchy is an array where every key has it's children keys inside it. $top_level_parents is an array which collects all tables who doesn't have any parent with key being table name and value being it's occurrences.

      然后我们调用另一个函数traverseHierarchy遍历所有这些顶级父级并获取其子级.这样,我们将始终在孩子之前拜访父母,因为我们首先要迭代父母(即使对将要成为其他表的父母的孩子也有效).

      We then call another function traverseHierarchy to traverse over all of these top level parents and get their children as well. This way, we will always visit parents before children, since we are iterating parents first(even valid for it's children who would be in turn parents for other tables).

      为更好地解释,这两个数组如下所示:

      To better explain, both arrays would look something like below:

      $层次结构:

      Array
      (
          [test] => Array
              (
                  [0] => test2
                  [1] => test3
              )
      
          [test2] => Array
              (
              )
      
          [test4] => Array
              (
              )
      
          [test5] => Array
              (
                  [0] => test6
              )
      
          [test6] => Array
              (
              )
      
          [test3] => Array
              (
                  [0] => test5
              )
      )
      

      $ top_level_parents:

      Array
      (
          [test] => 2
          [test4] => 1
      )
      

      第2部分:

      function traverseHierarchy($hierarchy,$top_level_parents,&$result){
          foreach($top_level_parents as $each_parent => $occurrences){
              while($occurrences-- > 0){
                  $result[] = [
                      'table' => $each_parent,
                      'parent_table' => NULL
                  ];
              }       
      
              traverseChildren($hierarchy,$each_parent,$result);
          }
      }
      

      • 在这里,我们遍历所有顶级父级,并将它们存储在result数组中,并带有no.它们发生在原始阵列中的次数.

        • Here, we are iterating over all top level parents, storing them in the result array with the no. of times they occurred in the original array.

          完成后,我们现在遍历它的孩子,并将其所有孩子也包括在结果数组中.

          Once done, we would now traverse it's children and include all it's children in the result array as well.

          第3部分:

          function traverseChildren($hierarchy,$parent,&$result){
              foreach($hierarchy[$parent] as $each_child){
                  $result[] = [
                      'table' => $each_child,
                      'parent_table' => $parent
                  ];
          
                  traverseChildren($hierarchy,$each_child,$result);
              }
          }
          

          • 在这里,我们遍历所有子项并将它们包括在result中.这个孩子很有可能也有自己的孩子.因此,我们将使用深度优先搜索来递归收集它们.这样,我们始终确保父母先于孩子.

            • Here, we iterate over all children and include them in the result. It is quite possible that this child could have it's own children as well. So, we would recursively collect them all using depth first search. This way we are always ensuring parent comes before child.

              在上一节中,我们仅打印结果.

              In the last section, we just print the result.

              这篇关于PHP usort用于字符串层次结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆