对多个数组进行组合讨论

WBOY
發布: 2016-06-23 14:21:40
原創
866 人瀏覽過

排列组合

假设有三个数组(实际不确定多少个数组):
$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),
    ...
);
不想用递归,但是也可以实现看看

回复讨论(解决方案)

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

$a = [1, 2];$b = ['A', 'B', 'C'];$c = ['a', 'b'];$d = Descartes($a, $b, $c);print_r($d);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);      if($k==0) sort($v);    }, $n);  array_unshift($d, 'array_merge');  $d = call_user_func_array('array_map', $d);  array_multisort(array_map(function($v) { return $v[0]; }, $d), $d);  return $d;}
登入後複製
Array(    [0] => Array        (            [0] => 1            [1] => A            [2] => a        )    [1] => Array        (            [0] => 1            [1] => A            [2] => b        )    [2] => Array        (            [0] => 1            [1] => B            [2] => a        )    [3] => Array        (            [0] => 1            [1] => B            [2] => b        )    [4] => Array        (            [0] => 1            [1] => C            [2] => a        )    [5] => Array        (            [0] => 1            [1] => C            [2] => b        )    [6] => Array        (            [0] => 2            [1] => A            [2] => a        )    [7] => Array        (            [0] => 2            [1] => A            [2] => b        )    [8] => Array        (            [0] => 2            [1] => B            [2] => a        )    [9] => Array        (            [0] => 2            [1] => B            [2] => b        )    [10] => Array        (            [0] => 2            [1] => C            [2] => a        )    [11] => Array        (            [0] => 2            [1] => C            [2] => b        ))
登入後複製

嗯,这个是对的。#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)
登入後複製
登入後複製

嗯,这个是对的。#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)
登入後複製
登入後複製


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

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);    }  }
登入後複製

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

除了简化 array() 为 [], 和使用了闭包写法外,没有什么新东西
闭包可用 create_function 函数改写
嗯,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;}
登入後複製

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));
登入後複製
登入後複製

不现丑了,收藏了再说。

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));
登入後複製
登入後複製

这个简单明了 
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
最新問題
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板