如下需求
需要将用户选择的01,02,03,04这4个号码按照两个数为一组的组合下注,并且按照顺序,每个组合不会因为大小顺序,重复出现多次
通过手工计算我们可以得到
["01", "02"],["01", "03"],["01", "04"],["02", "03"],["02", "04"],["03", "04"]
共计6个组合
像这种计算我们可以使用简单的for循环来实现组合
$checkedData = ["01","02","03","04"];
$boxData = [];
for ($i = 0; $i < count($checkedData); $i++) {
$tempData = [$checkedData[$i]];
foreach ($checkedData as $v) {
if ($checkedData[$i] == $v) continue;
$boxData[] = array_merge($tempData, [$v]);
}
}
#输出结果
[
["01","02"],
["01","03"],
["01","04"],
["02","01"],
["02","03"],
["02","04"],
["03","01"],
["03","02"],
["03","04"],
["04","01"],
["04","02"],
["04","03"]
]
实际使用两个for循环会输出12种组合,这不是我们所需要的,因为每个数都出现了先后顺序重复
改良后的代码
$checkedData = ["01","02","03","04"];
$boxData = [];
for ($i = 0; $i < count($checkedData); $i++) {
$tempData = [$checkedData[$i]];
#每循环一次,就减去一个数组
$bData = array_slice($checkedData, $i + 1);
foreach ($bData as $v) {
$boxData[] = array_merge($tempData, [$v]);
}
}
#输出结果
[
["01","02"],
["01","03"],
["01","04"],
["02","03"],
["02","04"],
["03","04"]
]
嗯,没毛病,这就是我们想要的结果,想法是美好的,但现实却是扯淡的。
现在两个数为一组这个算法是写好了,但是呢,人类的脑袋壳子不知道是怎么搞得,总有各种想法和需求,强大到你无法想象
如什么连、什么串、什么全中不中的。。。
然后就出现了,需要3个、4个、5个、6个。。。n个数为一组的排列组合,这可怎么搞?按照上面的代码,两个数为一组需要嵌套两个循环,N个就要N个循环,那代码得写成啥样?
$checkedData = ["01","02","03","04"];
$boxData = [];
for ($i = 0; $i < count($checkedData); $i++) {
$tempData = [$checkedData[$i]];
#每循环一次,就减去一个数组
$bData = array_slice($checkedData, $i + 1);
foreach ($bData as $bk => $v) {
$cData = array_slice($bData, $bk + 1);
foreach ($cData ) {
foreach ($dData ) {
...
}
}
}
}
没错,如果按照组合个数不断增加这样的需要,就是多少个组合就要多少个循环,这些写肯定是不行的,这里我们就需要介绍下语言的递归操作了,就是调用方法本身,让其自成一个无限循环,直到处理结果返回
改良后的代码
function combination($data, $len){
$boxData = [];
$n = count($data);
if ($len <= 0 || $len > $n) {
return $boxData;
}
for ($i = 0; $i < $n; $i++) {
$tempData = [$data[$i]];
if ($len == 1) {
$boxData[] = $tempData;
} else {
$b = array_slice($data, $i + 1);
$c = combination($b, $len - 1);
foreach ($c as $v) {
$boxData[] = array_merge($tempData, $v);
}
}
}
return $boxData;
}
$checkedData = ["01","02","03","04","05","06","07","08"];
$data = combination($checkedData,2);//两组
$data = combination($checkedData,3);//三组
以此类推......
还有一种需求
需要将[0,1,2],[2,3,4],[5,6,7],[7,8,9],[1,2,3,4,5]这样复杂的数组,拆分成3个、4个、5个数为每一组的不重复数据,像什么星啦、什么同不同号啦、什么胆啦,需要用到。
嗯,废话不多说了,主要是我感觉你应该懂了,直接上代码
#len为需要多少个数组合
function GetCombinationData($lists,$len = 5){
//二维数组列表必须等于设定的len,否则不能组合
if (count($lists) < $len) return false;
$resLists = [];
foreach ($lists as $k => $v) {
$resLists = SetCombinationData($v);
}
return $resLists;
}
function SetCombinationData($val){
//静态变量,保存上一个的值
static $resLists = [];
if (empty($resLists)) {
$resLists = $val;
}else{
// 临时数组保存结合的结果
$tempLists = [];
//循环
foreach ($resLists as $k => $v) {
foreach ($val as $key => $value) {
$tempLists[$k . '_' . $key] = $v . ',' . $value;
}
}
$resLists = $tempLists;
}
return $resLists;
}
$checkedData = [[0,1,2],[2,3,4],[5,6,7],[7,8,9],[1,2,3,4,5]];
$result = GetCombinationData($checkedData,5);
var_dump($result);
网友评论