对多个数组进行组合讨论

WBOY
Release: 2016-06-23 14:21:40
Original
865 people have browsed it

排列组合

假设有三个数组(实际不确定多少个数组):
$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;}
Copy after login
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        ))
Copy after login

嗯,这个是对的。#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;}
Copy after login
Copy after login
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)
Copy after login
Copy after login

嗯,这个是对的。#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;}
Copy after login
Copy after login
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)
Copy after login
Copy after login


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

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);    }  }
Copy after login

除了简化 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;}
Copy after login

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));
Copy after login
Copy after login

不现丑了,收藏了再说。

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));
Copy after login
Copy after login

这个简单明了 
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template