PHP多数组组合-颜色尺码大小
抽象一下需求:
在构建某个对象时,它拥有多个属性,每个属性拥有多个可选的值,需要穷举出每个属性不同的选择组合构建出的不同对象,比如:
输入参数:
$arr = [ 'Name' => ['Jack', 'Lily', 'Martin'], 'Age' => ['18', '12'], 'Gender' => ['male', 'female'], 'Address' => ['Alexander', 'Huston', 'NewYork'], ];
从每个属性中取一个值,根据排列组合计算知道可以得到 36 个不同的人。
期望结果:
篇幅原因,中间省略掉。
array ( 0 => array ( 'Name' => 'Jack', 'Age' => '18', 'Gender' => 'male', 'Address' => 'Alexander', ), 1 => array ( 'Name' => 'Jack', 'Age' => '18', 'Gender' => 'male', 'Address' => 'Huston', ), ... 34 => array ( 'Name' => 'Martin', 'Age' => '12', 'Gender' => 'female', 'Address' => 'Huston', ), 35 => array ( 'Name' => 'Martin', 'Age' => '12', 'Gender' => 'female', 'Address' => 'NewYork', ),)
实现代码:
/** * 排列组合 * @param $arr * @return array */ function pac($arr){ if (empty($arr)) { return []; } $n = count($arr); // 维度数量 $count = 1; // 结果总数 $size = []; // 每个属性的可选值个数 $visit = []; // 每个属性当前访问到的位置(下标) $keyIndex = []; // 保存每个属性的key $res = []; // 保存结果 // 初始化 $i = 0; foreach ($arr as $key => $values) { $size[$i] = count($values); $visit[$i] = 0; $count *= count($values); $keyIndex[$i] = $key; $i ++; } $m = 0; $temp = []; while (true) { for ( $i = 0; $i < $n; $i++ ) { // 取当前位置的下一个位置记录到最终的数组中 $temp[$m][$i] = $visit[$i] + 1; } $m ++; for ( $i = $n - 1; $i >= 0; $i-- ) { // 取的是可选值的最后一个值时,重置位置记录,下一个组合从0位置开始 if ($visit[$i] == $size[$i] - 1) { $visit[$i] = 0; } else { // 当前属性未取完 break; } } // 当所有属性的值都取完了,经过最后一次$i--, $i 值变为 -1,循环完成 if ($i < 0) { break; } // 位置后移 $visit[$i] ++; } for ($i = 0; $i < $count; $i ++) { for ($j = 0; $j < $n; $j ++) { $res[$i][$keyIndex[$j]] = $arr[$keyIndex[$j]][$temp[$i][$j]-1]; } } return $res; }
如果需求是想要从多个元素中取n个出来,得到多种不同的结果,如果可选元素集合为,n为2,这样传值:
$arr = [ ['a', 'b','c'], ['a', 'b','c'],];
得到的结果(部分):
array ( 0 => array ( 0 => 'a', 1 => 'a', ), 1 => array ( 0 => 'a', 1 => 'b', ), ... 7 => array ( 0 => 'c', 1 => 'b', ), 8 => array ( 0 => 'c', 1 => 'c', ),)