我只想找出更好的方法来做到这一点:
$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
然后对b
和c
进行相同的操作。目前,我正在使用以下代码:
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()仍然会消耗更多的内存。
我希望它会有所帮助,至少对我而言这很有趣;)