-3

PHP で配列の自動ツリーを作成する際に問題があります。元。私の配列には2、3、3の数字があり、手動でツリーを作成できます。

<?
$source_arr = array(2,3,3);

for($x=0; $x<$source_arr[0]; $x++){ // level 0: 2 loops

for ($xx=0; $xx<$source_arr[1]; $xx++) {  // level 1: 3 loops

    for ($xxx=0; $xxx<$source_arr[2]; $xxx++) {  // level 2: 3 loops

        $new[] = "$x$xx$xxx";

   }    
    }
}   

echo "<pre>";
print_r($new);
echo "</pre>";

?>

結果:

配列
(
    [0] => 000
    [1] => 001
    [2] => 002
    [3] => 010
    [4] => 011
    [5] => 012
    [6] => 020
    [7] => 021
    [8] => 022
    [9] => 100
    [10] => 101
    [11] => 102
    [12] => 110
    [13] => 111
    [14] => 112
    [15] => 120
    [16] => 121
    [17] => 122
)

しかし、私はそれを自動化したいのですが、次のように、異なる値を持つさまざまな数のレベル配列があります: 11 レベル:

$source_arr = array(8,5,10,12,5,8,12,5,6,10,8);

そして、自動の大きなツリーを構築したいと考えています。PHP array_walk または array_walk_recursive で可能ですか? 再帰的なカテゴリ ツリーの構築に関する投稿を見つけましたが、それらのコードを適応させることはできません。

編集:無限配列を実行してメモリを使い果たしたくありません。配列の数が 15 項目を超えることはありません。値の範囲は 3 ~ 16 です。

4

2 に答える 2

3

ツリーの反復は再帰的に実行する必要があります。ツリーの深さには制限がないため、選択の余地はありませんが、ループのネストレベルは固定されています。あなたはツリーを構築していませんが、リストの構築は確かにツリートラバーサルです。再帰関数には次のパラメーターが必要です。

  • 現在のノードの識別。ここでは、ノードのレベルとその親から構築されたプレフィックス文字列を使用できます。
  • ツリーの各レベルのサイズ。配列source_arrのリストから取得でき、現在のレベルはすでに提供されています。
  • 構築中のアレイ

結果はreturnとmergeによっても生成される可能性がありますが、それはより単純ではなく、効率が低下します。

<?php

function build(array &$sizes, array &$result, $prefix, $level)
{
  if ($level == count($sizes)) {
    $result[] = $prefix;
  }
  else {
    for ($i = 0 ; $i < $sizes[$level] ; $i++) {
      build($sizes, $result, $prefix . $i, $level + 1);
    }
  }
}


$sizes = array(8,5,10,12);
$result = array();
build($sizes, $result, '', 0);

echo "<pre>";
print_r($result);
echo "</pre>";

?>

要求しているツリーは巨大であり、PHPは結果を出力する前にメモリを使い果たしてしまうことに注意してください。

于 2012-09-29T15:07:39.677 に答える
0

機能していると思われる別のソリューションを次に示します。あまりきれいではありません、私は知っています。しかしねえ!再帰はありません!;)

<?php

function generate(array $a) {
  $multArray = function($mult, $e) {
    return $mult * $e;
  };

  $finalSize = array_reduce($a, $multArray, 1);

  $res = array();
  $aReverse = array_reverse($a);
  for ($i = 0; $i < $finalSize; $i++) {
    $tmpReverseRes = array();
    foreach ($aReverse as $k => $v) {
      $mult = array_reduce(array_slice($aReverse, 0, $k), $multArray, 1);
      $tmpReverseRes[] = (int)($i / $mult) % $v;
    }
    $res[] = join('', array_reverse($tmpReverseRes));
  }

  return $res;
}

$a = array(2, 3, 3);

print_r(generate($a));

アップデート:

クラスでそれを実装することもできます:

<?php
class StrangeGenerator {
  private $a = null;
  private $aReverse = null;
  private $combinationsCount = null;

  public function __construct(array $array) {
    $this->a = $array;
    $this->aReverse = array_reverse($array);
    $this->combinationsCount = array_reduce($array, 'self::multArray', 1);
  }

  public function getCombinationFor($index) {
    $this->checkRange($index);

    $revRes = array();
    foreach ($this->aReverse as $k => $v) {
      $mult = array_reduce(array_slice($this->aReverse, 0, $k), 'self::multArray', 1);
      $revRes[] = (int)($index / $mult) % $v;
    }
    return join('', array_reverse($revRes));
  }

  public function getCombinationsCount() {
    return $this->combinationsCount;
  }

  protected function checkRange($index) {
    if ($index < 0 || $index >= $this->combinationsCount) {
      throw new RangeException('Out of range');
    }
  }

  protected static function multArray($mult, $e) {
    return $mult * $e;
  }
}

$a = array(2, 3, 3);

$g = new StrangeGenerator($a);

$count = $g->getCombinationsCount();

for ($i = 0; $i < $count; $i++) {
  $res = $g->getCombinationFor($i);
  echo "$res\n";
}

ところで、このクラスはすべての組み合わせをメモリに保持しているわけではありません。代わりにオンデマンドで計算されます。

于 2012-09-29T16:44:11.623 に答える