按id和父排序php数组

时间:2017-01-01 16:53:56

标签: php sorting

我有一个数组数组 - 每个数组都有自己的id和父id值。我想对它进行排序,以便每个孩子都应该在它的父母之下。让我告诉你我的代码:

Given Array:

$arr = array(array('id' => 15, 'parent' => 12), 
array('id' => 10, 'parent' => 12), 
array('id' => 12, 'parent' => 12), 
array('id' => 17, 'parent' => 12), 
array('id' => 21, 'parent' => 15), 
array('id' => 13, 'parent' => 15), 
array('id' => 15, 'parent' => 15), 
array('id' => 25, 'parent' => 15), 
array('id' => 7, 'parent' => 7), 
array('id' => 18, 'parent' => 7), 
array('id' => 4, 'parent' => 7), 
array('id' => 1, 'parent' => 3), 
array('id' => 5, 'parent' => 5), 
array('id' => 2, 'parent' => 7));

输出应该如何(父母asc,每个孩子也升序 - 总是在父母之下(父母总是作为第一个!!!)):

      0 =>
          'id' => int 1
          'parent' => int 3
      1 =>
          'id' => int 5
          'parent' => int 5
      2 =>
          'id' => int 7
          'parent' => int 7
      3 =>
          'id' => int 2
          'parent' => int 7
      4 =>
          'id' => int 4
          'parent' => int 7
      5 =>
          'id' => int 18
          'parent' => int 7
      6 =>
          'id' => int 12
          'parent' => int 12
      7 =>
          'id' => int 10
          'parent' => int 12
      8 =>
          'id' => int 15
          'parent' => int 12
      9 =>
          'id' => int 17
          'parent' => int 12
      10 =>
          'id' => int 15
          'parent' => int 15
      11 =>
          'id' => int 13
          'parent' => int 15
      12 =>
          'id' => int 21
          'parent' => int 15
      13 =>
          'id' => int 25
          'parent' => int 15

问题:我想知道实现这一目标的最简单方法是什么?我已经设法做到了,但我不能停止这种感觉,有一种方法可以更快,更优化的方式做到这一点..

Here is my code:

function groupByParent ($array)
{
    $groups = array();
    foreach ($array as $a) {
        $groups[$a['parent']][] = $a;
    }
    return $groups;
}
function insideSort ($array)
{
    foreach ($array as $k => $v) {
        usort($array[$k], function($a, $b){
           return $a['id'] == $b['parent'] ? -1 : 1;
        });
        $f = array_shift($array[$k]);
        sort($array[$k]);
        array_unshift($array[$k], $f);
    }
    return $array;
}
function finalSort($array)
{
    $final = array();
    foreach ($array as $a) {
        $final = array_merge($final, $a);
    }
    return $final;
}

$grr = groupByParent($arr);
$irr = insideSort($grr);
ksort($irr);
$res = finalSort($irr);

有更简单的方法来实现它吗?

干杯

1 个答案:

答案 0 :(得分:1)

<强>解释

对数组进行排序的另一种方法是迭代遍历数组中的所有元素,并查找所有不同的父项,然后存储找到的每个父项的所有兄弟,除了id与父项相同的一次。然后我们将它升序排序并将id与父级相同的节点添加到数组的开头。

大O符号

此算法的运行时间最好是O(n),最差的情况是O(n ^ 2)。

<强>代码

<?php

$arr = array(
    array('id' => 15, 'parent' => 12), 
    array('id' => 10, 'parent' => 12), 
    array('id' => 12, 'parent' => 12), 
    array('id' => 17, 'parent' => 12), 
    array('id' => 21, 'parent' => 15), 
    array('id' => 13, 'parent' => 15), 
    array('id' => 15, 'parent' => 15), 
    array('id' => 25, 'parent' => 15), 
    array('id' => 7, 'parent' => 7), 
    array('id' => 18, 'parent' => 7), 
    array('id' => 4, 'parent' => 7), 
    array('id' => 1, 'parent' => 3), 
    array('id' => 5, 'parent' => 5), 
    array('id' => 2, 'parent' => 7)
);

/* Declare variables */
$result = array();
$temp = array();
$parents = array();

/* Get all distinct parents and sort ascending */
for ($i = 0; $i < count($arr); $i++)
    if (!isset($temp[$arr[$i]['parent']]))
        $temp[$arr[$i]['parent']] = array();

ksort($temp);

/* Find all siblings with same parent */
for ($i = 0; $i < count($arr); $i++)
    if ($arr[$i]['parent'] === $arr[$i]['id'])
        $parents[] = $arr[$i]['parent'];
    else
        $temp[$arr[$i]['parent']][$arr[$i]['id']] = true;

/* Sort siblings ascending */
foreach ($temp as $key => $value)
    ksort($temp[$key]);

/* Prepend node where id is same as parent if existing */
for ($i = 0; $i < count($parents); $i++)
    $temp[$parents[$i]] = array($parents[$i] => true) + $temp[$parents[$i]];

/* Display properly */
foreach ($temp as $key => $value)
    foreach ($temp[$key] as $subKey => $subValue)
        $result[] = array('id' => $subKey, 'parent' => $key);

/* Output */
print_r($result);

?>

执行时间

Execution time for my code:
Execution 1: 0.00018095970153809
Execution 2: 0.00018692016601562
Execution 3: 0.00022411346435547
Execution 4: 0.00018596649169922
Execution 5: 0.00018620491027832
Execution 6: 0.00018501281738281
Execution 7: 0.00018501281738281
Execution 8: 0.00018596649169922
Execution 9: 0.00018095970153809
Execution 10: 0.00020003318786621

Average: 0.00019011497

Execution time for your code:
Execution 1: 0.00019311904907227
Execution 2: 0.0001978874206543
Execution 3: 0.00019693374633789
Execution 4: 0.0001981258392334
Execution 5: 0.0001990795135498
Execution 6: 0.00028491020202637
Execution 7: 0.00019598007202148
Execution 8: 0.00019693374633789
Execution 9: 0.0001978874206543
Execution 10: 0.00019717216491699

Average: 0.00020580291

结果是在代码的顶部和底部使用microtime(true)并从开始时间减去结束时间。

<强>结论

所以我提供的代码不一定是一种更容易实现你想要的东西的方法,但它看起来更有效率,特别是在使用像上面代码中的小数组时。

我没有在大数组上测试执行时间,建议您在选择解决方案之前这样做。

如果你设法找到摆脱“正确显示”部分(我的代码中的第48-50行)并且从头到尾正确存储数据的方法,那么执行时间会有很大改善。< / p> 祝你好运,祝新年快乐!