1

私がこの配列を持っていると仮定します:

Array
(
  [0] => Array
  (
    [name] => ELECTRONICS
    [depth] => 0
  )

  [1] => Array
  (
    [name] => TELEVISIONS
    [depth] => 1
  )

  [2] => Array
  (
    [name] => TUBE
    [depth] => 2
  )

  [3] => Array
  (
    [name] => LCD
    [depth] => 2
  )

  [4] => Array
  (
    [name] => PLASMA
    [depth] => 2
  )

  [5] => Array
  (
    [name] => PORTABLE ELECTRONICS
    [depth] => 1
  )
)

前の要素よりも深い深さの直接の要素がキー「children」で前の要素の中に入るように、それを多次元配列に変換したいと思います。このような:

Array
(
  [0] => Array
  (
    [name] => ELECTRONICS
    [depth] => 0
    [children] => Array
    (
      [0] => Array
      (
        [name] => TELEVISIONS
        [depth] => 1
        [children] => Array
        (
          [0] => Array
          (
            [name] => TUBE
            [depth] => 2
          )

          [1] => Array
          (
            [name] => LCD
            [depth] => 2
          )

          [2] => Array
          (
            [name] => PLASMA
            [depth] => 2
          )
        )
      )

      [1] => Array
      (
        [name] => PORTABLE ELECTRONICS
        [depth] => 1
      )
    )
  )
)

よろしくお願いします。ありがとう ;)

4

3 に答える 3

2

これが私のクラックです... foreachループとポインターの配列を使用して、さまざまな親ポインターの束を追跡します。

$multi_dimensional = array();
$last_depth = 0;
$parent = &$multi_dimensional;
$parents[$last_depth] = &$parent;


foreach ($start as $idx => $data) {
  // same/increasing depth
  if ($last_depth <= $data['depth']) {
    $parent['children'][] = $data;  
  } 

  // increasing depth
  if ($last_depth < $data['depth']) {
    $parents[$last_depth] = &$parent;
  }

  // decreasing depth
  if ($last_depth > $data['depth']) {
    $parent = &$parents[$data['depth']-1];
    $parent['children'][] = $data;  
  }

  // look ahead and prepare parent in increasing
  if (isset($start[$idx+1]) && $start[$idx+1]['depth'] > $data['depth']) {
    $last_insert_idx = count($parent['children'])-1;
    $parent = &$parent['children'][$last_insert_idx];
  }
  $last_depth = $data['depth'];
}

// initial values are in child "children" array
$result = $multi_dimensional['children'];
于 2013-02-19T17:05:58.633 に答える
2

それはトリッキーなものでした。これがこれを達成するための最適な方法であるかどうかはわかりませんが、うまくいきます:

function flat_to_tree($array, $depth = 0)
{
  $out = array();
  $inCurrentDepth = true;

  foreach ($array as $key => $value) {
    if ($value['depth'] < $depth) {
      return $out;
    }

    if ($value['depth'] === $depth) {
      $inCurrentDepth = true;
      $out[] = $value;
    }

    if ($inCurrentDepth && $value['depth'] > $depth) {
      $inCurrentDepth = false;
      $out[$key - 1]['children'] = flat_to_tree(array_slice($array, $key), $value['depth']);
    }
  }

  return $out;
}
于 2013-02-19T16:54:43.847 に答える
1

名前とその再帰的な性質についてお詫び申し上げます。また、この関数は元の配列を「破棄」することに注意してください。保持する場合は、クローンを使用してください。

function multiDimensionate(&$arr, $currentLevel = 0) {
  $root = array();

  foreach ($arr as &$elem){
    if ($elem["depth"] == $currentLevel) {
      $root[] = $elem;
      unset($elem);
    } else if ($elem["depth"] == $currentLevel + 1) {
      $root[count($root)-1]["children"] = multiDimensionate($arr,$elem["depth"]);      
    }
  }

  return $root;
}

編集:コメントで指摘されているように、前の関数は正しく機能していませんでしたが、これは問題ないはずですが、元の配列を破壊するという副作用があります。

于 2013-02-19T16:31:25.770 に答える