我只想找出更好的方法来做到这一点:

$array = array(
    array('a', 'b', 'c'),
    array('e', 'f', 'g'),
    array('h', 'i', 'j', 'k', 'l')
);
目标是打印如下内容:
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
然后对bc进行相同的操作。
目前,我正在使用以下代码:
foreach ($array[0] as $val1) {
    foreach ($array[1] as $val2) {
        foreach ($array[2] as $val3) {
            echo "$val1  $val2  $val3 \n";
        }
        echo "--------\n";
    }
}
我还尝试动态创建上述代码,并使用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);
但如果可能的话,我仍然想找到更好的方法。
更新:
注意:$array是动态的,它可能包含两个或更多子数组

最佳答案

我尝试了另一种方法,但最终以类似于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 );

带有示例数据:
$array = array(
    array('a', 'b', 'c'),
    array('e', 'f', 'g'),
    array('h', 'i', 'j', 'k', 'l')
);

它将输出:
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] =>
                )

        )

)

然后,它需要其他代码来绘制预期结果:
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 );

生产 :
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

正如我所说的,如果您不需要这种结果树(您的问题没有提及,我只是在搜索最佳方法时就提出了),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 );

它返回以下数组:
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
)

然后很容易达到预期的结果:
echo implode( "\n", $combinations )."\n";

将输出:
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

起初,我认为我的解决方案比使用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

但是,当使用更大的输入值时,它变得更加重要:
$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')
);

getCombinations给出:
drawCombinations(  getCombinations( $array ));

echo memory_get_usage()." ". memory_get_peak_usage()."\n";

// 242376 253008

扩展给出:
echo implode( "\n", expand( $array ) )."\n";

echo memory_get_usage()." ". memory_get_peak_usage()."\n";

//242544 704520

如果我们看一下每个函数生成的数组,原因很明显,因为第一个解决方案存储的重复值较少(我不确定PHP如何处理以树的每个分支结尾的重复数组)。

再一次,取决于您要达成的目标,您是否在乎。

快速“回显”每一行而不是创建一个较大的结果数组,这会稍微减少内存峰值问题,但随着数据集的增长,expand()仍然会消耗更多的内存。

我希望它会有所帮助,至少对我而言这很有趣;)

10-06 14:58