php实现的笛卡儿积
之前在网上找到一个大牛写的版本(网址已经记不得了。。),如下
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 function Descartes1() 2 { //Cartesian product of arrays or strings or something else except empty array 3 //note that when there is only one argent, it must be an array with more than one elements, otherwise it will result in an warning and wrong result 4 $t = func_get_args(); 5 6 if(func_num_args() == 1) return call_user_func_array( __FUNCTION__, $t[0] ); 7 8 $a = array_shift($t); 9 10 if(! is_array($a)) $a = array($a); 11 12 $a = array_chunk($a, 1); 13 14 do { 15 $r = array(); 16 $b = array_shift($t); 17 if(! is_array($b)) $b = array($b); 18 19 foreach($a as $p) 20 foreach(array_chunk($b, 1) as $q) 21 $r[] = array_merge($p, $q); 22 23 $a = $r; 24 25 }while($t); 26 27 return $r; 28 }
在实际使用过程中,若输入的 数组过大,则会导致内存不够用,于是 就将其改为了 yield 版本,如下:
1 function Descartes() 2 { 3 $args = func_get_args(); 4 if (func_num_args() == 1 && is_array($args[0])) $args=$args[0]; 5 6 $i = 0; 7 $args_len = []; 8 9 while ($i < count($args)){//modify each argument to array 10 $args_len[] = is_array($args[$i]) ? ( count($args[$i++]) - 1 ) : (int) ( ($args[$i] = array($args[$i])) && ++$i ) - 1; 11 #$args_len[] = is_array($args[$i]) ? count($args[$i])-1 : 0; 12 #$i++; 13 } 14 15 foreach(Descartes_yield($args_len, $args) as $e){ 16 yield $e; 17 } 18 } 19 20 function Descartes_yield($arr_len, $arr_data) 21 { 22 $len = count($arr_len); 23 $temp_arr = array_pad(array(), $len, 0); 24 $temp_arr[0]--; 25 26 while($temp_arr != $arr_len) { 27 $temp_arr[0]++; 28 29 $i = 0; 30 $result = []; 31 32 while ($i < $len) { 33 if ($temp_arr[$i] > $arr_len[$i]) { 34 $temp_arr[$i] = 0; 35 $temp_arr[$i+1]++; 36 } 37 $i++; 38 } 39 $i=0; 40 while($i < $len) { 41 $result[$i] = $arr_data[$i][$temp_arr[$i]]; 42 $i++; 43 } 44 45 yield $result; 46 } 47 }
下面是测试代码:
#Descartes(array(1,2),["a","b"],3);
# 测试代码:
# foreach ( Descartes( array(1,2), ["a","b"], 3) as $descar )
# print_r( $descar );
不知道 速度 会不会比之前的慢,不过至少在 大量数据 做笛卡儿积的时候,可以跑起来了~
又看到一个写的特别棒的,原文网址https://skyverd.com/php_array_function_cartesian/,如下:
1 $arr = array( 2 array("a","b"), 3 range(1,100), 4 array("A","B","C") 5 ); 6
7
8 9 fun($arr); 10 print_r($res); 11 12 function fun($arr, $tmp = array()) 13 { 14 foreach(array_shift($arr) as $v) 15 { 16 $tmp[] = $v; 17 if($arr) 18 { 19 fun($arr, $tmp); 20 } 21 else 22 { 23 $GLOBALS["res"][] = implode(",", $tmp); 24 25 } 26 array_pop($tmp); 27 } 28 }
简单的测试了一下:
//memory_limit = 512M, 64位 range(1,10000000);//7个零,只有该数组时,php直接报错 $arr = array( array("a","b"), range(1,100000), // 5个零 array("A","B","C") );//三个版本都正常运行 $arr1 = array( array("a","b"), range(1,1000000), // 6个零 array("A","B","C") );//版本1,3直接报错,内存不够,版本2运行良好