10 php recursion loops multidimensional-array
我想简单地找到更好的方法来做到这一点:
$array = array(
array('a', 'b', 'c'),
array('e', 'f', 'g'),
array('h', 'i', 'j', 'k', 'l')
);
Run Code Online (Sandbox Code Playgroud)
目标是打印这样的东西:
a e h
a e i
a e j
a e k
a e l
a f h
a f i
a f j
a f k
a f l
a g h
a g i
a g j
a g k
a g l
Run Code Online (Sandbox Code Playgroud)
然后为b和做同样的事情c.
foreach ($array[0] as $val1) {
foreach ($array[1] as $val2) {
foreach ($array[2] as $val3) {
echo "$val1 $val2 $val3 \n";
}
echo "--------\n";
}
}
Run Code Online (Sandbox Code Playgroud)
我还尝试动态创建上面的代码并使用eval执行它:
$eval = '
$data =array();
';
$eval_blocks = '';
$eval_foreach = '';
$eval_data = '
$data[] = ';
$looplength = count($array);
for ($i = 0; $i < $looplength; $i++) {
$eval_foreach .= '
foreach($array[' . $i . '] as $val' . ($i + 1) . '){
';
if (($i + 1) == $looplength) {
$eval_data .= ' $val' . ($i + 1) . ';';
} else {
$eval_data .= ' $val' . ($i + 1) . ' ." ".';
}
$eval_blocks .= '
}
';
}
$eval = $eval . $eval_foreach . $eval_data . $eval_blocks;
eval($eval);
print_r($data);
Run Code Online (Sandbox Code Playgroud)
但是如果可能的话,我仍然希望找到更好的方法.
更新:
注意:它$array是动态的,它可能包含两个子数组或更多
小智 5
我尝试了另一种方法,但最终以类似于Valentin CLEMENT的解决方案结束,尽管我的功能更加冗长.
尽管如此,原创性的是这个函数会为你提供一个组合树,根据你打算做什么,它可能(或可能不是)有用.
这是代码:
function getCombinations( $arrayList, $index = 0 )
{
$subCombinations = $combinations = '';
if ( $index < count( $arrayList )-1 )
{
$subCombinations = getCombinations( $arrayList, $index+1 );
}
foreach( $arrayList[$index] as $item )
{
$combinations[$item] = $subCombinations ;
}
return $combinations;
}
$combinations = getCombinations( $array );
print_r( $combinations );
Run Code Online (Sandbox Code Playgroud)
使用示例数据:
$array = array(
array('a', 'b', 'c'),
array('e', 'f', 'g'),
array('h', 'i', 'j', 'k', 'l')
);
Run Code Online (Sandbox Code Playgroud)
它将输出:
Array
(
[a] => Array
(
[e] => Array
(
[h] =>
[i] =>
[j] =>
[k] =>
[l] =>
)
[f] => Array
(
[h] =>
[i] =>
[j] =>
[k] =>
[l] =>
)
[g] => Array
(
[h] =>
[i] =>
[j] =>
[k] =>
[l] =>
)
)
[b] => Array
(
[e] => Array
(
[h] =>
[i] =>
[j] =>
[k] =>
[l] =>
)
[f] => Array
(
[h] =>
[i] =>
[j] =>
[k] =>
[l] =>
)
[g] => Array
(
[h] =>
[i] =>
[j] =>
[k] =>
[l] =>
)
)
[c] => Array
(
[e] => Array
(
[h] =>
[i] =>
[j] =>
[k] =>
[l] =>
)
[f] => Array
(
[h] =>
[i] =>
[j] =>
[k] =>
[l] =>
)
[g] => Array
(
[h] =>
[i] =>
[j] =>
[k] =>
[l] =>
)
)
)
Run Code Online (Sandbox Code Playgroud)
然后它需要额外的代码来绘制预期的结果:
function drawCombinations( $combinations, $line = array() )
{
foreach( $combinations as $value => $children )
{
array_push( $line, $value );
if ( is_array( $children ) )
{
drawCombinations( $children, $line );
}
else
{
echo implode( " ", $line ) ." \n";
}
array_pop( $line );
}
}
drawCombinations( $combinations );
Run Code Online (Sandbox Code Playgroud)
生产 :
a e h
a e i
a e j
a e k
a e l
a f h
a f i
a f j
a f k
a f l
a g h
a g i
a g j
a g k
a g l
b e h
b e i
b e j
b e k
b e l
b f h
b f i
b f j
b f k
b f l
b g h
b g i
b g j
b g k
b g l
c e h
c e i
c e j
c e k
c e l
c f h
c f i
c f j
c f k
c f l
c g h
c g i
c g j
c g k
c g l
Run Code Online (Sandbox Code Playgroud)
正如我所说的那样,如果你不需要这个结果树(你的问题没有提及,我只是在搜索最佳方式时产生了这个),Valentin CLEMENT的方法可能会更好(如果你不使用太大的数据集) ,我会解释为什么之后).
我以一种我认为更具可读性和可用性的方式对其进行了重写:
function expand( $array, $from = 0, $length = false )
{
if ( $length === false )
{
$length = count( $array );
}
if ( $length == $from )
{
return array('');
}
else
{
$result = array();
foreach( $array[$from] as $x )
{
foreach( expand( $array, $from+1, $length ) as $tail )
{
$result[] = trim("$x $tail");
}
}
return $result;
}
}
$combinations = expand( $array );
print_r( $combinations );
Run Code Online (Sandbox Code Playgroud)
它返回以下数组:
Array
(
[0] => a e h
[1] => a e i
[2] => a e j
[3] => a e k
[4] => a e l
[5] => a f h
[6] => a f i
[7] => a f j
[8] => a f k
[9] => a f l
[10] => a g h
[11] => a g i
[12] => a g j
[13] => a g k
[14] => a g l
[15] => b e h
[16] => b e i
[17] => b e j
[18] => b e k
[19] => b e l
[20] => b f h
[21] => b f i
[22] => b f j
[23] => b f k
[24] => b f l
[25] => b g h
[26] => b g i
[27] => b g j
[28] => b g k
[29] => b g l
[30] => c e h
[31] => c e i
[32] => c e j
[33] => c e k
[34] => c e l
[35] => c f h
[36] => c f i
[37] => c f j
[38] => c f k
[39] => c f l
[40] => c g h
[41] => c g i
[42] => c g j
[43] => c g k
[44] => c g l
)
Run Code Online (Sandbox Code Playgroud)
然后很容易达到预期的结果:
echo implode( "\n", $combinations )."\n";
Run Code Online (Sandbox Code Playgroud)
将输出:
a e h
a e i
a e j
a e k
a e l
a f h
a f i
a f j
a f k
a f l
a g h
a g i
a g j
a g k
a g l
b e h
b e i
b e j
b e k
b e l
b f h
b f i
b f j
b f k
b f l
b g h
b g i
b g j
b g k
b g l
c e h
c e i
c e j
c e k
c e l
c f h
c f i
c f j
c f k
c f l
c g h
c g i
c g j
c g k
c g l
Run Code Online (Sandbox Code Playgroud)
起初,我认为我的解决方案比Valentin的解决方案耗费更多的内存,因为它使用数组,但是当我测试它时,我意识到它确实使用的内存略少.
根据这两种方法显示内存指标得出了以下结果:
drawCombinations( getCombinations( $array ));
echo memory_get_usage()." ". memory_get_peak_usage()."\n";
// 238736 244896
echo implode( "\n", expand( $array ) )."\n";
echo memory_get_usage()." ". memory_get_peak_usage()."\n";
// 238912 252304
Run Code Online (Sandbox Code Playgroud)
但是当使用更大的输入值时,它变得更加重要,具有:
$array = array(
array('a', 'b', 'c'),
array('e', 'f', 'g'),
array('h', 'i', 'j', 'k', 'l'),
array('m', 'n', 'o', 'p', 'q', 'r', 's'),
array('t', 'u', 'v', 'x', 'y', 'z')
);
Run Code Online (Sandbox Code Playgroud)
getCombinations给出:
drawCombinations( getCombinations( $array ));
echo memory_get_usage()." ". memory_get_peak_usage()."\n";
// 242376 253008
Run Code Online (Sandbox Code Playgroud)
展开给出:
echo implode( "\n", expand( $array ) )."\n";
echo memory_get_usage()." ". memory_get_peak_usage()."\n";
//242544 704520
Run Code Online (Sandbox Code Playgroud)
如果我们查看每个函数生成的数组,原因很明显,因为第一个解决方案存储的重复值较少(我不确定PHP如何处理结束树的每个分支的重复数组).
再一次,取决于你明白的目标,你会关心与否.
动态地"回送"每一行而不是创建一个大的结果数组会略微减少内存峰值问题,但随着数据集的增长,expand()仍会消耗更多内存.
我希望它有所帮助,至少对我来说这很有趣;)
这应该有效:
function expand($arr){
function recexpand($arr, $from, $len) {
if ($from == $len) {
yield "\n";
} else {
foreach($arr[$from] as $x) {
foreach(expand($arr, $from+1, $len) as $tail) {
yield "$x $tail";
}
}
}
}
return recexpand($arr, 0, count($arr);
}
$array = array(
array('a', 'b', 'c'),
array('e', 'f', 'g'),
array('h', 'i', 'j', 'k', 'l')
);
foreach(expand($array) as $row) {
echo $row;
}
Run Code Online (Sandbox Code Playgroud)
回声:
a e h
a e i
a e j
a e k
a e l
a f h
a f i
a f j
a f k
a f l
a g h
a g i
a g j
a g k
a g l
b e h
b e i
b e j
b e k
b e l
b f h
b f i
b f j
b f k
b f l
b g h
b g i
b g j
b g k
b g l
c e h
c e i
c e j
c e k
c e l
c f h
c f i
c f j
c f k
c f l
c g h
c g i
c g j
c g k
c g l
Run Code Online (Sandbox Code Playgroud)
我不是 PHP 专家,因此可能有一种更惯用的编写方式,但它适用于任何长度的数组。
对于 PHP<5(或任何没有“yield”语句的版本)
a e h
a e i
a e j
a e k
a e l
a f h
a f i
a f j
a f k
a f l
a g h
a g i
a g j
a g k
a g l
b e h
b e i
b e j
b e k
b e l
b f h
b f i
b f j
b f k
b f l
b g h
b g i
b g j
b g k
b g l
c e h
c e i
c e j
c e k
c e l
c f h
c f i
c f j
c f k
c f l
c g h
c g i
c g j
c g k
c g l
Run Code Online (Sandbox Code Playgroud)