假设有三个数组(实际不确定多少个数组):
$arr1 = array(1, 2, 3, 4);
$arr2 = array(10, 20, 30, 40);
$arr3 = array(100, 200, 300, 400);要实现的结果:
array(
    array(1,10,100),
    array(1,10,200),
    array(1,10,300),
    array(1,10,400),
    array(1,20,100),
    array(1,20,200),
    array(1,20,300),
    array(1,20,400),
    array(1,30,100),
    ...
);
不想用递归,但是也可以实现看看排列组合

解决方案 »

  1.   

    本帖最后由 xuzuning 于 2013-09-12 07:58:13 编辑
      

  2.   

    嗯,这个是对的。#1 的有些毛病,传入4个数组就不对了$a = [1, 2];
    $b = ['A', 'B', 'C'];
    $c = ['a', 'b'];
    $d = ['D', 'E', 'F'];$r = Descartes($a, $b, $c);
    $r = Descartes($a, $b, $c, $d);print_r( array_map(function($v) { return join(',', $v); }, $r) );function Descartes() {
      $d = func_get_args();
      if( count($d) < 2 ) return current($d);
      $n = array_product( array_map('count', $d) );
      array_walk( $d, function(&$v, $k, $n) {
          $v = array_chunk( call_user_func_array('array_merge', array_pad([$v], $n/count($v), $v)), 1);
        }, $n);
      foreach($d as $i=>$t) {
        if($i == 0) {
          $r = $t;
        }else {
          array_multisort(array_map(function($v) { return $v[0]; }, $r), $r);
          $r = array_map('array_merge', $r, $t);
        }
      }
      return $r;
    }
    Array
    (
        [0] => 1,A,a,D
        [1] => 1,A,a,E
        [2] => 1,A,a,F
        [3] => 1,A,b,D
        [4] => 1,A,b,E
        [5] => 1,A,b,F
        [6] => 1,B,a,D
        [7] => 1,B,a,E
        [8] => 1,B,a,F
        [9] => 1,B,b,D
        [10] => 1,B,b,E
        [11] => 1,B,b,F
        [12] => 1,C,a,D
        [13] => 1,C,a,E
        [14] => 1,C,a,F
        [15] => 1,C,b,D
        [16] => 1,C,b,E
        [17] => 1,C,b,F
        [18] => 2,A,a,D
        [19] => 2,A,a,E
        [20] => 2,A,a,F
        [21] => 2,A,b,D
        [22] => 2,A,b,E
        [23] => 2,A,b,F
        [24] => 2,B,a,D
        [25] => 2,B,a,E
        [26] => 2,B,a,F
        [27] => 2,B,b,D
        [28] => 2,B,b,E
        [29] => 2,B,b,F
        [30] => 2,C,a,D
        [31] => 2,C,a,E
        [32] => 2,C,a,F
        [33] => 2,C,b,D
        [34] => 2,C,b,E
        [35] => 2,C,b,F
    )
      

  3.   


    看的有点晕,得慢慢看,用到了很多以前很少用的函数,不过这个中括号是什么写法? 5.3.12不支持
    array_pad([$v], $n/count($v), $v)
      

  4.   

    array() 可简化为 [] 是 php5.4 才有的吗?我怎么记得 php5.3 就是的呢?简单注释一下:
      $d = func_get_args();//读取传入的参数到数组(php4)
      if( count($d) < 2 ) return current($d);
      $n = array_product( array_map('count', $d) ); //array_product 计算数组值的乘积(php5),array_map 返回经回调函数处理的数组(php4)
      array_walk( $d, function(&$v, $k, $n) {//用回调函数处理数组元素(php3)闭包写法(php5.3)
          $v = array_chunk( call_user_func_array('array_merge', array_pad([$v], $n/count($v), $v)), 1);
        }, $n);//array_chunk 切割数组(php4)
          //call_user_func_array 调用指定函数并传递参数数组(php4)对执行可变参数数量的函数很有用
      foreach($d as $i=>$t) {
        if($i == 0) {
          $r = $t;
        }else {
          array_multisort(array_map(function($v) { return $v[0]; }, $r), $r);
          $r = array_map('array_merge', $r, $t);
        }
      }
      

  5.   

    除了简化 array() 为 [], 和使用了闭包写法外,没有什么新东西
    闭包可用 create_function 函数改写
      

  6.   

    嗯,5.3没有这种语法。怎么感觉php的语法和javascript的越来越像
    多谢版主
    我自己也写了个,比较啰嗦
    function arr_combina3(){
        $args = func_get_args();
        $num = count($args);
        if(empty($args)){
            return array();
        }else if($num == 1){
            return $args[0];
        }
        $arr = array();
        $i = 0;
        $j = 0; // 当前使用数组下标
        $last_index = $num - 1;
        // 按传入顺序循环使用传入的参数数组
        while($j <= $last_index){
            if($j == $last_index){ // 当前使用数组为最后参数数组时
                // 将最后传入的参数数组每一项分别加入组合
                $tmp = $arr[$i];
                foreach($args[$j] as $k=>$v){
                    $t = $tmp;
                    $t[] = $v;
                    $arr[$i] = $t;
                    ++$i;
                }
                // 反向循环查找参数数组是否已使用完
                for($n=$j-1; $n>=0; --$n){
                    $t = current($args[$n]);
                    // 检测是否已到数组末尾
                    if(empty($t)){ // 已到数组末尾
                        if(0==$n){ // 已经是第一个数组的末尾,说明组合完成,停止组合
                            $num = 0;
                            break 2;
                        }
                        reset($args[$n]);
                    }else{ // 未到末尾时,修改当前使用数组下标
                        $j = $n;
                        // 去除已到最后的项
                        $arr[$i] = array_slice($tmp, 0, $n, true);
                        break;
                    }
                }
                unset($tmp);
            }else{
                // 将当前使用数组当前指针指向的值加入到组合数组
                $arr[$i][] = current($args[$j]);
                next($args[$j]);// 当前使用数组指针前移一位
                ++$j; // 当前使用数组下标+1
            }
        }
        unset($args);
        return $arr;
    }
      

  7.   

    function my_arr_combine()
    {
    $args = func_get_args();
    $final = array_shift($args);
    while($f = array_shift($args))
    {
    $r = array();
    foreach($final as $v)
    {
    foreach($f as $v2)
    {
    $r[] = array_merge(is_array($v)?$v:array($v),array($v2));
    }
    }
    $final = $r;
    }
    return $final;
    }
    $arr1 = array(1, 2, 3, 4);
    $arr2 = array(10, 20, 30, 40);
    $arr3 = array(100, 200, 300, 400);
    $data = array($arr1,$arr2,$arr3);
    echo "<pre/>";
    print_r(call_user_func_array('my_arr_combine', $data));