Php 基于父/子关系对数组值排序

Php 基于父/子关系对数组值排序,php,arrays,sorting,Php,Arrays,Sorting,我试图对数组进行排序,以确保数组中任何项的父项始终位于它之前。例如: Array ( [0] => Array ( [0] => 207306 [1] => Bob [2] => ) [1] => Array ( [0] => 199730 [1] => Sam

我试图对数组进行排序,以确保数组中任何项的父项始终位于它之前。例如:

Array
(
    [0] => Array
        (
            [0] => 207306
            [1] => Bob
            [2] => 
        )

    [1] => Array
        (
            [0] => 199730
            [1] => Sam
            [2] => 199714
        )

    [2] => Array
        (
            [0] => 199728
            [1] => Simon
            [2] => 207306
        )

    [3] => Array
        (
            [0] => 199714
            [1] => John
            [2] => 207306
        )

    [4] => Array
        (
            [0] => 199716
            [1] => Tom
            [2] => 199718
        )

    [5] => Array
        (
            [0] => 199718
            [1] => Phillip
            [2] => 207306
        )

    [6] => Array
        (
            [0] => 199720
            [1] => James
            [2] => 207306
        )

)
在上面的数组中,此“失败”,因为[1][2](Sam)不存在,[4][2](Tom)也不存在

在本例中,正确的输出应该是Sam和Tom的父母在出现在数组中之前已经存在:

Array
(
    [0] => Array
        (
            [0] => 207306
            [1] => Bob
            [2] => 
        )

    [1] => Array
        (
            [0] => 199714
            [1] => John
            [2] => 207306
        )


    [2] => Array
        (
            [0] => 199730
            [1] => Sam
            [2] => 199714
        )

    [3] => Array
        (
            [0] => 199728
            [1] => Simon
            [2] => 207306
        )


    [4] => Array
        (
            [0] => 199718
            [1] => Phillip
            [2] => 207306
        )


    [5] => Array
        (
            [0] => 199716
            [1] => Tom
            [2] => 199718
        )

    [6] => Array
        (
            [0] => 199720
            [1] => James
            [2] => 207306
        )

)
我找到了一个非常接近的答案,但似乎只深入了一层(即,只有一位家长),而在我的情况下,层次结构中可能有1到10层


如何对数组进行排序,使其在其父数组之前已存在,否则不会显示任何值?

这种方法如何:

创建一个空数组
result

在数组上循环,只在[2]为空的地方从数组中取出项目,然后将它们插入到
result

完成此循环后,在
while
-循环中使用
foreach
-循环。使用
foreach
-循环,您可以将[2]已经是
结果的一部分的数组中的每一项取出。只要数组包含任何内容,就可以执行此操作

$result = array();
$result[''] = 'root';

while(!empty($yourArray)){
  foreach($yourArray as $i=>$value){
    if(isset($result[$value[2]])){
      // use the next line only to show old order
      $value['oldIndex'] = $i;
      $result[$value[0]] = $value;
      unset($yourArray[$i]);
    }
  }
}

unset($result['']);
PS:您可能会在走过阵列时移除阵列的某些部分而遇到麻烦。如果你这样做。。。尝试解决此问题:)


PPS:如果您的数组有一个未解决的循环或一个子元素没有父元素,请考虑一个中断条件。

这将简单地对数组进行排序(在O(n)中),首先是所有没有父元素的数组,然后是父元素已经在数组中的数组,迭代,直到没有子元素将当前元素作为父元素

# map the children by parent
$parents = ['' => []];
foreach ($array as $val) {
    $parents[$val[2]][] = $val;
}
# start with those with no parent
$sorted = $parents[''];
# add the children the current nodes are parent of until the array is empty
foreach ($sorted as &$val) {
    if (isset($parents[$val[0]])) {
        foreach ($parents[$val[0]] as $next) {
            $sorted[] = $next;
        }
    }
}
此代码需要PHP7,在某些情况下在PHP5下可能无法工作。-对于PHP5兼容性,您必须将
foreach($sorted as&$val)
交换为($val=reset($sorted);$val;$val=next($sorted))


现场演示:

我为您准备了两个不同的版本

a) 使用带有递归和引用的“遍历树”方法来最小化内存消耗

$data = [
    [207306,'Bob',''], [199730,'Sam',199714],
    [199728,'Simon',207306], [199714,'John',207306],
    [199716, 'Tom',199718], [199718,'Phillip',207306],
    [199720,'James',207306]
];

$list = [];
generateList($data, '', $list);

var_dump($list);

function generateList($data, $id, &$list) {
    foreach($data as $d) {
        if($d[2] == $id) {          
            $list[] = $d; // Child found, add it to list            
            generateList($data, $d[0], $list); // Now search for childs of this child
        }
    }
}
b) 使用内置的phps u
usort()
函数(似乎只适用于php5.x,而不适用于php7+)


我在PHP5.6和PHP7中检查了这一点

示例阵列:

$array = Array(0 => Array(
        0 => 207306,
        1 => 'Bob',
        2 => '',
    ),
    1 => Array
        (
        0 => 199730,
        1 => 'Sam',
        2 => 199714,
    ),
    2 => Array
        (
        0 => 199728,
        1 => 'Simon',
        2 => 207306,
    ),
    3 => Array
        (
        0 => 199714,
        1 => 'John',
        2 => 207306,
    ),
    4 => Array
        (
        0 => 199716,
        1 => 'Tom',
        2 => 199718,
    ),
    5 => Array
        (
        0 => 199718,
        1 => 'Phillip',
        2 => 207306,
    ),
    6 => Array
        (
        0 => 199720,
        1 => 'James',
        2 => 207306,
    ),
); 



echo "<pre>";
$emp = array();

//form the array with parent and child
foreach ($array as $val) {
    $manager = ($val[2] == '') ? 0 : $val[2];
    $exist = array_search_key($val[2], $emp);
    if ($exist)
        $emp[$exist[0]][$val[0]] = $val;
    else
    //print_R(array_search_key(199714,$emp));
        $emp[$manager][$val[0]] = $val;
}

$u_emp = $emp[0];
unset($emp[0]);

//associate the correct child/emp after the manager
foreach ($emp as $k => $val) {
    $exist = array_search_key($k, $u_emp);
    $pos = array_search($k, array_keys($u_emp));

    $u_emp = array_slice($u_emp, 0, $pos+1, true) +
            $val +
            array_slice($u_emp, $pos-1, count($u_emp) - 1, true);

}
print_R($u_emp); //print the final result

// key search function from the array
function array_search_key($needle_key, $array, $parent = array())
{
    foreach ($array AS $key => $value) {
        $parent = array();
        if ($key == $needle_key)
            return $parent;
        if (is_array($value)) {
            array_push($parent, $key);
            if (($result = array_search_key($needle_key, $value, $parent)) !== false)
                return $parent;
        }
    }
    return false;
}
$array=array(0=>array(
0 => 207306,
1=>“鲍勃”,
2 => '',
),
1=>数组
(
0 => 199730,
1=>“山姆”,
2 => 199714,
),
2=>数组
(
0 => 199728,
1=>“西蒙”,
2 => 207306,
),
3=>数组
(
0 => 199714,
1=>“约翰”,
2 => 207306,
),
4=>数组
(
0 => 199716,
1=>“汤姆”,
2 => 199718,
),
5=>数组
(
0 => 199718,
1=>“菲利普”,
2 => 207306,
),
6=>数组
(
0 => 199720,
1=>“詹姆斯”,
2 => 207306,
),
); 
回声“;
$emp=array();
//使用父级和子级构成数组
foreach($val形式的数组){
$manager=($val[2]='')0:$val[2];
$exist=array\u search\u key($val[2],$emp);
如果($存在)
$emp[$exist[0]][$val[0]]=$val;
其他的
//打印(数组搜索键(199714,$emp));
$emp[$manager][$val[0]]=$val;
}
$u_emp=$emp[0];
未结算($emp[0]);
//在经理之后关联正确的子项/emp
foreach($k=>$val的emp){
$exist=数组\搜索\密钥($k,$u\ emp);
$pos=数组搜索($k,数组键($u-emp));
$u_emp=数组_切片($u_emp,0,$pos+1,真)+
$val+
数组切片($u\u emp,$pos-1,count($u\u emp)-1,true);
}
打印(单位:emp)//打印最终结果
//数组中的键搜索函数
函数数组\搜索\键($needle\键,$array,$parent=array())
{
foreach($key=>$value的数组){
$parent=array();
如果($key==$needle\u key)
返回$parent;
if(是_数组($value)){
数组\u push($parent,$key);
if($result=array\u search\u key($needle\u key,$value,$parent))!==false)
返回$parent;
}
}
返回false;
}

您可以在变量$arr中使用数组,并使用此代码,它将为您提供所需的输出

$a=array(array(207306,'Bob',''),
array (199730,'Sam',199714),
array(199728,'Simon',207306),
array(199714,'John',207306),
array(199716,'Tom',199718),
array(199718,'Phillip',207306),
array(199720,'James',207306));

$sortedarray=$a;
foreach($a as $key=>$value){
    $checkvalue=$value[2];
    $checkkey=$key;
foreach($a as $key2=>$value2){
    if($key<$key2){
            if ($value2[0]===$checkvalue){
                $sortedarray[$key]=$value2;
                $sortedarray[$key2]=$value;
        }else{
            }
    }
  }
 }

 print_r($sortedarray);
函数检查($a,$b){
返回($a[0]==$b[2])?-1:1;
}
uasort($arr,'check');
回声';
打印(数组值($arr));
回声';

查找下面可能有用的代码。因此,您的输出存储在$sortedarray中

$a=array(array(207306,'Bob',''),
阵列(199730,'Sam',199714),
阵列(199728,'Simon',207306),
阵列(199714,'John',207306),
数组(199716,'Tom',199718),
阵列(199718,'Phillip',207306),
数组(199720,'James',207306));
$Darray=$a;
foreach($a作为$key=>$value){
$checkvalue=$value[2];
$checkkey=$key;
foreach($a作为$key2=>$value2){

如果($KEY请更清楚地解释您的问题。不清楚索引0和2处的每个数组中的整数值指的是什么,因为它们太大,无法引用任何现有索引。索引0是每个员工的ID,索引2是该员工的经理ID,这是经理ID的查找,因此,在上面的示例中,John有一个n ID为199714,其经理为207306,即Bob,因为Bob的ID为207306(index0)我正在考虑把这个问题选为闭幕,因为这是一个编码挑战,而不是一个真正的问题。你没有发表任何个人的尝试来解决这个问题,只是简单地张贴了一些数据和一个链接到一些已经给出的解决方案,真正的工作。遵守严格的标准,这是一个不好的问题。考虑重读。等待下一个问题的回答。这种存储关系的特殊方式称为。我使用的是PHP 5.6-您能突出显示您知道的任何不起作用的位吗?当循环位于最后一个元素并插入新元素时,循环将立即终止,而不是继续。解决方法是将foreach更改为
($val=重置($sorted);$val$
$array = Array(0 => Array(
        0 => 207306,
        1 => 'Bob',
        2 => '',
    ),
    1 => Array
        (
        0 => 199730,
        1 => 'Sam',
        2 => 199714,
    ),
    2 => Array
        (
        0 => 199728,
        1 => 'Simon',
        2 => 207306,
    ),
    3 => Array
        (
        0 => 199714,
        1 => 'John',
        2 => 207306,
    ),
    4 => Array
        (
        0 => 199716,
        1 => 'Tom',
        2 => 199718,
    ),
    5 => Array
        (
        0 => 199718,
        1 => 'Phillip',
        2 => 207306,
    ),
    6 => Array
        (
        0 => 199720,
        1 => 'James',
        2 => 207306,
    ),
); 



echo "<pre>";
$emp = array();

//form the array with parent and child
foreach ($array as $val) {
    $manager = ($val[2] == '') ? 0 : $val[2];
    $exist = array_search_key($val[2], $emp);
    if ($exist)
        $emp[$exist[0]][$val[0]] = $val;
    else
    //print_R(array_search_key(199714,$emp));
        $emp[$manager][$val[0]] = $val;
}

$u_emp = $emp[0];
unset($emp[0]);

//associate the correct child/emp after the manager
foreach ($emp as $k => $val) {
    $exist = array_search_key($k, $u_emp);
    $pos = array_search($k, array_keys($u_emp));

    $u_emp = array_slice($u_emp, 0, $pos+1, true) +
            $val +
            array_slice($u_emp, $pos-1, count($u_emp) - 1, true);

}
print_R($u_emp); //print the final result

// key search function from the array
function array_search_key($needle_key, $array, $parent = array())
{
    foreach ($array AS $key => $value) {
        $parent = array();
        if ($key == $needle_key)
            return $parent;
        if (is_array($value)) {
            array_push($parent, $key);
            if (($result = array_search_key($needle_key, $value, $parent)) !== false)
                return $parent;
        }
    }
    return false;
}
function check($a, $b) {   
    return ($a[0] == $b[2]) ? -1 : 1;
}


uasort($arr, 'check');
echo '<pre>';
print_r(array_values($arr));
echo '</pre>';
$a=array(array(207306,'Bob',''),
array (199730,'Sam',199714),
array(199728,'Simon',207306),
array(199714,'John',207306),
array(199716,'Tom',199718),
array(199718,'Phillip',207306),
array(199720,'James',207306));

$sortedarray=$a;
foreach($a as $key=>$value){
    $checkvalue=$value[2];
    $checkkey=$key;
foreach($a as $key2=>$value2){
    if($key<$key2){
            if ($value2[0]===$checkvalue){
                $sortedarray[$key]=$value2;
                $sortedarray[$key2]=$value;
        }else{
            }
    }
  }
 }

 print_r($sortedarray);