嵌套一个清单

时间:2015-02-12 13:12:44

标签: php arrays file nested

我花了几乎所有的时间尝试将这个类别的平面列表转换为嵌套列表,因为它应该是,因为它是一个5级深度类别列表。

以下是一个例子:

$array = 
array (
  array (
    'CategoryID' => '001',
    'CategoryLevel' => '1',
    'CategoryName' => 'Category 1',
    'CategoryParentID' => '001'
  ),
  array (
    'CategoryID' => '002',
    'CategoryLevel' => '2',
    'CategoryName' => 'Category 2',
    'CategoryParentID' => '001'
  ),
  array (
    'CategoryID' => '003',
    'CategoryLevel' => '3',
    'CategoryName' => 'Category 3',
    'CategoryParentID' => '002'
  ),
  array (
    'CategoryID' => '004',
    'CategoryLevel' => '4',
    'CategoryName' => 'Category 4',
    'CategoryParentID' => '003'
  ),
  array (
    'CategoryID' => '005',
    'CategoryLevel' => '5',
    'CategoryName' => 'Category 5',
    'CategoryParentID' => '004'
  )
);

我需要知道如何更改此数组,以便我可以在文本文件中将其转换为tab所指定的每个子类别。

Here's我一直在做的事情,以及here's我正在处理的实际数组。

$categories = array();
foreach ($array['CategoryArray']['Category'] as $category) {
  //echo print_r($category,1);
  echo 'category parent ID: '.$category['CategoryParentID']."\n";
  $array_search = recursive_array_search($category['CategoryParentID'], $categories);
  echo 'Array search: '.$array_search."\n";
  $index = isset($array_search) ? $array_search : false;
  echo 'index: '.print_r($index)."\n";
  if ($index) {
      //echo "\n\n=================".
      $category['CategoryID'].
      ' - '.
      $category['CategoryName'].
      ' (PARENT: '. $category['CategoryParentID'].
      ') =================';
      $value = eval('$categories'.$index);
      $value[$category['CategoryID']] = $category['CategoryName'];
  }
  else {
    //echo "\n\n=================".$category['CategoryID'].' - '.$category['CategoryName'].'=================';
    $categories[$category['CategoryParentID']][$category['CategoryID']] = $category['CategoryName'];
  }
}

1 个答案:

答案 0 :(得分:1)

我猜有问题的部分是(重新?)构建hierarchie但是一旦你有缩进输出不是问题。
没有测试过(边缘情况) - 但我相当自信....

<?php
$h = foo( getData() ) ;
var_export($h);

/* the assumption here is:
    when iterating $src the parent elements are always iterated before their respective child elements
    reverse the array and the opposite is true: the child element will always be iterated first
    -> ALL child elements are "waiting" for their respective parent element to "collect" them
    <-> when the parent element is iterated all its children have already been iterated

    Once an element is iterated it therefore
      - looks for its (previously iterated and stored) childnodes
      - "registers" itself in that storage array
        - unless its a root element (parentid==ownid), in which case it's registered as root element
*/
function foo(array $src) {
    $src = array_reverse($src);
    $toBeCollected = array(); // all the children waiting for their parents
    $retval = array();  // array of root elements

    foreach( $src as $e ) {
        // first we collect the children (if there are any)
        if ( isset($toBeCollected[ $e['CategoryID'] ]) ) {
            $e['childnodes'] = $toBeCollected[ $e['CategoryID'] ];
            unset($toBeCollected[ $e['CategoryID'] ]);
        }

        if ( $e['CategoryID']===$e['CategoryParentID'] ) {
            // it's a root element
            $retval[ $e['CategoryID'] ] = $e;
        }
        else {
            setEntry($toBeCollected, $e['CategoryParentID'], $e);
        }
    }

    return $retval;
}


function setEntry(array &$target, $key, $value) {
    if ( isset($target[$key]) ) {
        $target[$key][] = $value;
    }
    else {
        $target[$key] = array($value);
    }
}


function getData() {
    return array (
      array (
        'CategoryID' => '001',
        'CategoryLevel' => '1',
        'CategoryName' => 'Category 1',
        'CategoryParentID' => '001'
      ),
      array (
        'CategoryID' => '002',
        'CategoryLevel' => '2',
        'CategoryName' => 'Category 2',
        'CategoryParentID' => '001'
      ),
      array (
        'CategoryID' => '003',
        'CategoryLevel' => '3',
        'CategoryName' => 'Category 3',
        'CategoryParentID' => '002'
      ),
      array (
        'CategoryID' => '004',
        'CategoryLevel' => '4',
        'CategoryName' => 'Category 4',
        'CategoryParentID' => '003'
      ),
      array (
        'CategoryID' => '005',
        'CategoryLevel' => '5',
        'CategoryName' => 'Category 5',
        'CategoryParentID' => '004'
      ),
      array (
        'CategoryID' => '006',
        'CategoryLevel' => '2',
        'CategoryName' => 'Category 6',
        'CategoryParentID' => '001'
      )
    );
}

编辑:没有临时幼儿园的同样的事情

<?php
$h = foo( getData() ) ;
var_export($h);

/* the assumption here is:
    when iterating $src the parent elements are always iterated before their respective child elements
    reverse the array and the opposite is true: the child element will always be iterated first
    -> ALL child elements are "waiting" for their respective parent element to "collect" them
    <-> when the parent element is iterated all its children have already been iterated

    Once an element is iterated it therefore
      looks for its (previously iterated and stored) childnodes
        "registers" itself in that storage array
          unless its a root element (parentid==ownid), in which case it's registered as root element
*/
function foo(array $src) {
    $src = array_reverse($src);
    $nodes = array();

    foreach( $src as $e ) {
        // if there were child nodes "they" already created an entry in $nodes for this/current node
        if ( isset($nodes[$e['CategoryID']]) ) {
            // in this case the current node just "imports" the childnodes
            $e['childnodes'] = $nodes[$e['CategoryID']]['childnodes'];
            // "imports" means: node is moved, means: unset() on previous location
            unset($nodes[$e['CategoryID']]);
        }

        // now we check if the current node has a parent or is a root
        if ( $e['CategoryID']===$e['CategoryParentID'] ) {
            // it's a root -> gets stored under its own id
            $nodes[ $e['CategoryID'] ] = $e;
        }
        // it's a childnode -> create/append to stub for parent
        else  if ( isset($nodes[ $e['CategoryParentID'] ]) ) {
            // there already was another child -> append to stub
            $nodes[ $e['CategoryParentID'] ]['childnodes'][] = $e;
        }
        else {
            // first child visited -> create stub
            $nodes[ $e['CategoryParentID'] ] = array('childnodes' =>array($e));
        }
    }   
    return $nodes;
}



function getData() {
    return array (
      array (
        'CategoryID' => '001',
        'CategoryLevel' => '1',
        'CategoryName' => 'Category 1',
        'CategoryParentID' => '001'
      ),
      array (
        'CategoryID' => '002',
        'CategoryLevel' => '2',
        'CategoryName' => 'Category 2',
        'CategoryParentID' => '001'
      ),
      array (
        'CategoryID' => '003',
        'CategoryLevel' => '3',
        'CategoryName' => 'Category 3',
        'CategoryParentID' => '002'
      ),
      array (
        'CategoryID' => '004',
        'CategoryLevel' => '4',
        'CategoryName' => 'Category 4',
        'CategoryParentID' => '003'
      ),
      array (
        'CategoryID' => '005',
        'CategoryLevel' => '5',
        'CategoryName' => 'Category 5',
        'CategoryParentID' => '004'
      ),
      array (
        'CategoryID' => '006',
        'CategoryLevel' => '2',
        'CategoryName' => 'Category 6',
        'CategoryParentID' => '001'
      )
    );
}