-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 回答