PHP - 创建分层数组

时间:2011-12-28 20:13:15

标签: php arrays recursion tree

我甚至不确定如何开始写这个问题,但基本上,我有一个数组,看起来像这样:

Array
(
    [0] => /
    [1] => /404/
    [2] => /abstracts/
    [3] => /abstracts/edit/
    [4] => /abstracts/review/
    [5] => /abstracts/view/
    [6] => /admin/
    [7] => /admin/ads/
    [8] => /admin/ads/clickcounter/
    [9] => /admin/ads/delete/
    [10] => /admin/ads/edit/
    [11] => /admin/ads/list/
    [12] => /admin/ads/new/
    [13] => /admin/ads/sponsordelete/
    [14] => /admin/ads/sponsoredit/
    [15] => /admin/ads/sponsornew/
    [16] => /admin/ads/stats/
    [17] => /admin/boilerplates/
    [18] => /admin/boilerplates/deleteboiler/
    [19] => /admin/boilerplates/editboiler/
    [20] => /admin/boilerplates/newboilerplate/
    [21] => /admin/calendar/event/add/
    [22] => /admin/calendar/event/copy/
)

我需要'减少'/'处理'它到一个看起来像这样的数组:

Array
(
    [''] => Array()
    ['404'] => Array()
    ['abstracts'] => Array
                     (
                          [''] => Array()
                          ['edit'] => Array()
                          ['review'] => Array()
                          ['view'] => Array()
                     )
    ['admin'] => Array
                     (
                          ['ads'] => Array
                                     (
                                         [''] => Array()
                                         ['clickcounter'] => Array()
                                         ['delete'] =>Array()
                                         ['edit'] => Array()
                                     )
                     )
    .....
    .....   
)

那,如果手动初始化将看起来像这样:

$urlTree = array( ''         => array(),
                  '404'      => array(),
                  'abstracts'=> array( ''      => array(),
                                       'edit'  => array(),
                                       'review'=> array(),
                                       'view'  => array() ),
                  'admin'    => array( 'ads'=> array( ''            => array(),
                                                      'clickcounter'=> array(),
                                                      'delete'      => array(),
                                                      'edit'        => array() ) )
);

我通常偏离直接询问SO上的一大块代码,但有没有人可能有任何建议/代码可以遍历我的数组并将其转换为层次结构?

编辑:以下是我现在所拥有的一点,我知道这是一个可怜的小事,我今天只是把它搞清楚了。

  function loadUrlData()
  {
    // hold the raw data, /blah/blah/
    $urlData = array();

    $res = sql::query( "SELECT DISTINCT(`url`) FROM `pages` ORDER BY `url` ASC" );
    while( $row = sql::getarray( $res ) )
    {
      $urlData[] = explode( '/', substr( $row['url'], 1, -1 ) );
    }

    // populated, eventually, with the parent > child data
    $treeData = array();

    // a url
    foreach( $urlData as $k=> $v )
    {
      // the url pieces
      foreach( $v as $k2=> $v2 )
      {

      }
    }

    // $treeData eventually
    return $urlData;
  }

6 个答案:

答案 0 :(得分:2)

看起来相当容易。您希望遍历所有行(foreach),将它们拆分为多个部分(explode),循环遍历它们(foreach)并对它们进行分类。

由于您不喜欢要求大量代码,我不会提供任何代码。

<强>更新
解决这个问题的一个非常好的方法是引用$urlTree(使用&),循环遍历URL的每个部分,并继续将像$currentPosition这样的变量更新到URL中的当前部分树。因为您使用&,所以您可以直接编辑数组,同时仍使用简单变量。

更新2
这可能有效:

// a url
foreach( $urlData as $k=> $v )
{
  $currentSection = &$treeData;
  // the url pieces
  foreach( $v as $k2=> $v2 )
  {
    if (!isset($currentSection[$v2])) {
      $currentSection[$v2] = array();
    }

    $currentSection = &$currentSection[$v2];
  }
}

答案 1 :(得分:2)

我知道你没有要求一大堆代码,但我只是称之为小服务:

$map = array();
foreach($urls as $url) {
    $folders = explode('/', trim($url, '/'));

    applyChain($map, $folders, array());
}

function applyChain(&$arr, $indexes, $value) { //Here's your recursion
    if(!is_array($indexes)) {
        return;
    }

    if(count($indexes) == 0) {
        $arr = $value;
    } else {
        applyChain($arr[array_shift($indexes)], $indexes, $value);
    }
}

这很简单。我们将每个url分隔到其文件夹中(删除尾部和前导斜杠),然后沿阵列链向下工作,直到我们到达URL中提到的文件夹。然后我们在那里放置一个新的空数组并继续下一个URL。

答案 2 :(得分:1)

http://ideone.com/S9pWw

$arr = array(
    '/',
    '/404/',
    '/abstracts/',
    '/abstracts/edit/',
    '/abstracts/review/',
    '/abstracts/view/',
    '/admin/',
    '/admin/ads/',
    '/admin/ads/clickcounter/',
    '/admin/ads/delete/',
    '/admin/ads/edit/',
    '/admin/ads/list/',
    '/admin/ads/new/',
    '/admin/ads/sponsordelete/',
    '/admin/ads/sponsoredit/',
    '/admin/ads/sponsornew/',
    '/admin/ads/stats/',
    '/admin/boilerplates/',
    '/admin/boilerplates/deleteboiler/',
    '/admin/boilerplates/editboiler/',
    '/admin/boilerplates/newboilerplate/',
    '/admin/calendar/event/add/',
    '/admin/calendar/event/copy/');

$result = array();
foreach ($arr as $node) {
    $result = magic($node, $result);
}

var_dump($result);

function magic($node, $tree)
{
    $path = explode('/', rtrim($node, '/'));

    $original =& $tree;

    foreach ($path as $node) {
        if (!array_key_exists($node, $tree)) {
            $tree[$node] = array();
        }

        if ($node) {
            $tree =& $tree[$node];
        }
    }

    return $original;
}

答案 3 :(得分:1)

我的版本:

<?php
$srcArray = array(
    0 => '/',
    1 => '/404/',
    2 => '/abstracts/',
    3 => '/abstracts/edit/',
    4 => '/abstracts/review/',
    5 => '/abstracts/view/',
    6 => '/admin/',
    7 => '/admin/ads/',
    // ....
);
$tree = array();
foreach($srcArray as $str){
    $tmp = &$tree;
    $parts = explode('/', rtrim($str, '/'));
    foreach($parts as $part){
        if(!array_key_exists($part, $tmp)){
            $tmp[$part] = array();
        }
        $tmp = &$tmp[$part];
    }
}
var_dump($tree);

答案 4 :(得分:1)

<?php
$old_array = array("/", "/404/", "/abstracts/", "/abstracts/edit/", "/abstracts/review/", "/rrl/");
$new_array = array();

foreach($old_array as $woot) {
    $segments = explode('/', $woot);
    $current = &$new_array;
    for($i=1; $i<sizeof($segments); $i++) {
        if(!isset($current[$segments[$i]])){
            $current[$segments[$i]] = array();
        }
        $current = &$current[$segments[$i]];
    }
}

print_r($new_array);

?>

答案 5 :(得分:0)

您可以考虑将文本转换为JSON字符串,然后使用json_decode()生成结构。