具有深度的多维数组的数组

时间:2019-02-22 14:33:28

标签: php recursion

我有一个大问题(显然很容易解决),我已经尝试了24个多小时来创建一个函数,以深度将数组转换为多维。

我的数组是

$array = array(
    array("name" => "Root_1", "depth"=> "1"),
    array("name" => "Children","depth"=> "2"),
    array("name" => "Children", "depth"=> "2"),
    array("name" => "Children", "depth"=> "2"),
    array("name" => "Children","depth"=> "3"),
    array("name" => "Children","depth"=> "3"),
    array("name" => "Children","depth"=> "3"),
    array("name" => "Root_2", "depth"=> "1"),
    array("name" => "Children", "depth"=> "2"),
    array("name" => "Children", "depth"=> "2"),
    array("name" => "Children", "depth"=> "2")
)

我希望输出为:

$array = array(
  array("name" => "Root_1", "depth"=> "1", "children" => array(
        array("name" => "Children", "depth"=> "2", "children" => array()),
        array("name" => "Children", "depth"=> "2", "children" => array()),
        array("name" => "Children", "depth"=> "2", "children" => array(
                array("name" => "Children", "depth"=> "3", "children" => array()),
                array("name" => "Children", "depth"=> "3", "children" => array()),
                array("name" => "Children", "depth"=> "3", "children" => array())
            )
        )), 
  array("name" => "Root_2", "depth"=> "1", "children" => array(
        array("name" => "Children", "depth"=> "2", "children" => array()),
        array("name" => "Children", "depth"=> "2", "children" => array()),
        array("name" => "Children", "depth"=> "2", "children" => array(
                array("name" => "Children", "depth"=> "3", "children" => array()),
                array("name" => "Children", "depth"=> "3", "children" => array()),
                array("name" => "Children", "depth"=> "3", "children" => array())
            )
        )), 
);

我尝试过的事情:

<?php


function createArray($array, $depth) {
$result = array();
$item = array();


if(isset($array["depth"])) {
    if(intval($array["depth"]) >= $depth) {
        array_push($result, $array);
    }
} else {
    foreach($array as $value) {
        $depthToInt = intval($value["depth"]);
        if($depthToInt === $depth) {
            array_push($result, $value);
            $item = $value;
        } else {
            $item["children"] = createArray($value, $item["depth"]);
        }
    }
}
return $result; 

}

2 个答案:

答案 0 :(得分:3)

我来晚了,但是如果您对非递归解决方案感兴趣,这是一个简单的仅一次通过循环( O(n)):

<?php

function treeify(array $input): array
{
    $result = [];
    $path = [];

    foreach ($input as &$entry) {
        $entry['children'] = [];

        $depth = $entry['depth'] - 1;
        $path = \array_slice($path, 0, $depth);
        $path[] = &$entry;

        0 === $depth
            ? $result[] = &$entry
            : $path[$depth - 1]['children'][] = &$entry;
    }

    return $result;
}

print_r(treeify([
    ['name' => 'Root_1', 'depth' => 1],
        ['name' => 'Children', 'depth' => 2],
        ['name' => 'Children', 'depth' => 2],
        ['name' => 'Children', 'depth' => 2],
            ['name' => 'Children', 'depth' => 3],
            ['name' => 'Children', 'depth' => 3],
            ['name' => 'Children', 'depth' => 3],
                ['name' => 'Children', 'depth' => 4],
        ['name' => 'Children', 'depth' => 2],
    ['name' => 'Root_2', 'depth'=> 1],
        ['name' => 'Children', 'depth' => 2],
        ['name' => 'Children', 'depth' => 2],
        ['name' => 'Children', 'depth' => 2],
            ['name' => 'Children', 'depth' => 3],
    ['name' => 'Root_3', 'depth' => 1],
    ['name' => 'Root_4', 'depth' => 1],
        ['name' => 'Children', 'depth' => 2],
]));

演示:https://3v4l.org/1YkvY

答案 1 :(得分:2)

好的,很明显,我们需要一个递归解决方案。

对于每个项目(从虚拟根目录开始),我们要检索子级。假设我们通过过滤掉所有不是 孩子的孩子来获得孩子。

我们的过滤条件是什么?

  1. 孩子的深度比父母的深度大。
  2. 孩子的索引大于父索引。
  3. 孩子属于同一深度的物品块。让我们将其改组,因为子级的索引小于下一个块的开始。我们称这个索引小于限制。

所以我们需要:

  1. 获取给定索引,深度和限制的子级的函数。
  2. 获得给定索引限制的帮助器功能。

这就是我最后得到的。我认为这不是完美的选择(我隐约地怀疑我的极限逻辑),但是对于您的示例数据来说,大部分都在那儿。

$array = array(
    array( 'name' => 'Root_1', 'depth' => '1' ),
    array( 'name' => 'Children 1-1', 'depth' => '2' ),
    array( 'name' => 'Children 1-2', 'depth' => '2' ),
    array( 'name' => 'Children 1-2-1', 'depth' => '3' ),
    array( 'name' => 'Children 1-3', 'depth' => '2' ),
    array( 'name' => 'Children 1-3-1', 'depth' => '3' ),
    array( 'name' => 'Children 1-3-2', 'depth' => '3' ),
    array( 'name' => 'Children 1-3-3', 'depth' => '3' ),
    array( 'name' => 'Root_2', 'depth' => '1' ),
    array( 'name' => 'Children 2-1', 'depth' => '2' ),
    array( 'name' => 'Children 2-2', 'depth' => '2' ),
    array( 'name' => 'Children 2-3', 'depth' => '2' ),
    array( 'name' => 'Children 2-3-1', 'depth' => '3' ),
    array( 'name' => 'Children 2-3-2', 'depth' => '3' ),
    array( 'name' => 'Children 2-3-3', 'depth' => '3' ),
);

function getChildren( $array, $index = - 1 ) {

    $depth = isset( $array[ $index ]['depth'] ) ? (int) $array[ $index ]['depth'] : 0;
    $limit = $index === - 1 ? count( $array ) - 1 : findLimit( $array, $index );

    $result = array_filter( $array, function ( $item, $key ) use ( $index, $depth, $limit ) {

        $isDeeper      = (int) $item['depth'] === $depth + 1;
        $isAfter       = $key > $index;
        $isBeforeLimit = $key <= $limit;

        return $isDeeper && $isAfter && $isBeforeLimit;
    }, ARRAY_FILTER_USE_BOTH );

    foreach ( $result as $key => $item ) {
        $result[ $key ]['children'] = getChildren( $array, $key );
    }

    return $result;
}

function findLimit( $array, $index ) {
    $depth   = (int) $array[ $index ]['depth'];
    $limit   = $index;
    $current = $limit + 1;

    while ( isset( $array[ $current ] ) && ( (int) $array[ $current ]['depth'] > $depth ) ) {
        $current ++;
        $limit ++;
    }

    return $limit;
}

$result = getChildren( $array );

var_dump( $result );

结果:

array(2) {
  [0]=>
  array(3) {
    ["name"]=>
    string(6) "Root_1"
    ["depth"]=>
    string(1) "1"
    ["children"]=>
    array(3) {
      [1]=>
      array(3) {
        ["name"]=>
        string(12) "Children 1-1"
        ["depth"]=>
        string(1) "2"
        ["children"]=>
        array(0) {
        }
      }
      [2]=>
      array(3) {
        ["name"]=>
        string(12) "Children 1-2"
        ["depth"]=>
        string(1) "2"
        ["children"]=>
        array(1) {
          [3]=>
          array(3) {
            ["name"]=>
            string(14) "Children 1-2-1"
            ["depth"]=>
            string(1) "3"
            ["children"]=>
            array(0) {
            }
          }
        }
      }
      [4]=>
      array(3) {
        ["name"]=>
        string(12) "Children 1-3"
        ["depth"]=>
        string(1) "2"
        ["children"]=>
        array(3) {
          [5]=>
          array(3) {
            ["name"]=>
            string(14) "Children 1-3-1"
            ["depth"]=>
            string(1) "3"
            ["children"]=>
            array(0) {
            }
          }
          [6]=>
          array(3) {
            ["name"]=>
            string(14) "Children 1-3-2"
            ["depth"]=>
            string(1) "3"
            ["children"]=>
            array(0) {
            }
          }
          [7]=>
          array(3) {
            ["name"]=>
            string(14) "Children 1-3-3"
            ["depth"]=>
            string(1) "3"
            ["children"]=>
            array(0) {
            }
          }
        }
      }
    }
  }
  [8]=>
  array(3) {
    ["name"]=>
    string(6) "Root_2"
    ["depth"]=>
    string(1) "1"
    ["children"]=>
    array(3) {
      [9]=>
      array(3) {
        ["name"]=>
        string(12) "Children 2-1"
        ["depth"]=>
        string(1) "2"
        ["children"]=>
        array(0) {
        }
      }
      [10]=>
      array(3) {
        ["name"]=>
        string(12) "Children 2-2"
        ["depth"]=>
        string(1) "2"
        ["children"]=>
        array(0) {
        }
      }
      [11]=>
      array(3) {
        ["name"]=>
        string(12) "Children 2-3"
        ["depth"]=>
        string(1) "2"
        ["children"]=>
        array(3) {
          [12]=>
          array(3) {
            ["name"]=>
            string(14) "Children 2-3-1"
            ["depth"]=>
            string(1) "3"
            ["children"]=>
            array(0) {
            }
          }
          [13]=>
          array(3) {
            ["name"]=>
            string(14) "Children 2-3-2"
            ["depth"]=>
            string(1) "3"
            ["children"]=>
            array(0) {
            }
          }
          [14]=>
          array(3) {
            ["name"]=>
            string(14) "Children 2-3-3"
            ["depth"]=>
            string(1) "3"
            ["children"]=>
            array(0) {
            }
          }
        }
      }
    }
  }
}