求一个PHP计算数组内元素的不同组合,请看案例
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了求一个PHP计算数组内元素的不同组合,请看案例相关的知识,希望对你有一定的参考价值。
比如 我要计算 $arr = array(a,b,c,d,,,,,,,,,);的不同组合 ,并且规定指定所有组合 开始必须是a,结束必须是d, 那么我们得到下面的结果是:
ad abd acd abcd, 这里面的a b c d是指的的任意内容 不限制个数,只是规定第一个值和最后一个值
哪位大神有算法 万分感谢 我实在想不到
我举个例子吧 比如我有 abcd四个内容,,那直接要得到的结果是 比如2位数的有 ad
3位数的有 abd acd 4位数的有 abcd acbd
组合有标准算法。只是你要区分组合和排列的概念,组合与顺序无关,下abcd、acbd是一个组合,4个里面取4个形成组合只有一种情况;排列与顺序有关,abcd、acbd是不同的排列,4个里面取4个形成的排列种数有24种(4*3*2*1)。
排列和组合都有标准的算法,非常经典,百度可以查到,各类编程书籍上也有。
给定数组php中r元素的所有组合
【中文标题】给定数组php中r元素的所有组合【英文标题】:All combinations of r elements from given array php 【发布时间】:2015-01-26 09:18:00 【问题描述】:给定一个数组,如下所示
$array = ('1', '2', '3', '4', '5', '6', '7');
我正在寻找一种方法来生成所有可能的组合,每个组合所需的元素数量最少。 (例如,如果 r = 5 那么它将返回包含至少 5 个元素的所有可能组合)
【问题讨论】:
我设法用大约 50 行代码完成了它,我得到了 29 个可能的组合。我相信这是正确的答案,考虑到n = 7
,它是数组中元素的数量,以及r = 5
。所以我们有7C5 + 7C6 + 7C7 = 29
。这是你所期待的吗?
这似乎是正确的,你能发布你的代码吗?
【参考方案1】:
k
和 n
项目的组合可以使用以下函数递归定义:
function combinationsOf($k, $xs)
if ($k === 0)
return array(array());
if (count($xs) === 0)
return array();
$x = $xs[0];
$xs1 = array_slice($xs,1,count($xs)-1);
$res1 = combinationsOf($k-1,$xs1);
for ($i = 0; $i < count($res1); $i++)
array_splice($res1[$i], 0, 0, $x);
$res2 = combinationsOf($k,$xs1);
return array_merge($res1, $res2);
以上是基于递归定义选择k
out n
元素,可以在列表中固定一个元素x
,有C(k-1, xs\x)
组合包含x
(即@ 987654329@) 和不包含x
的C(k,xs\xs)
组合(即代码中的res2
)。
完整示例:
$array = array('1', '2', '3', '4', '5', '6', '7');
function combinationsOf($k, $xs)
if ($k === 0)
return array(array());
if (count($xs) === 0)
return array();
$x = $xs[0];
$xs1 = array_slice($xs,1,count($xs)-1);
$res1 = combinationsOf($k-1,$xs1);
for ($i = 0; $i < count($res1); $i++)
array_splice($res1[$i], 0, 0, $x);
$res2 = combinationsOf($k,$xs1);
return array_merge($res1, $res2);
print_r ($array);
print_r(combinationsOf(5,$array));
//print_r(combinationsOf(5,$array)+combinationsOf(6,$array)+combinationsOf(7,$array));
【讨论】:
【参考方案2】:一个组合可以表示为
nCr = n! / (r! - (n - r)!)
首先,我们将$n
确定为数组中元素的数量。而$r
是每个组合中元素的最小数量。
$a = ['1', '2', '3', '4', '5', '6', '7']; // the array of elements we are interested in
// Determine the `n` and `r` in nCr = n! / (r! * (n-r)!)
$r = 5;
$n = count($a);
接下来,我们将$max
确定为$n
二进制数字可以表示的最大数。也就是说,如果$n = 3
,那么$max = (111)
2 = 7
。为此,我们首先创建一个空字符串$maxBinary
,并在其中添加$n
数量的1
s。然后我们将其转换为十进制,并将其存储在$max
。
$maxBinary = "";
for ($i = 0; $i < $n; $i++)
$maxBinary .= "1";
$max = bindec($maxBinary); // convert it into a decimal value, so that we can use it in the following for loop
然后,我们列出从0
到$max
的每一个二进制数,并存储其中有超过$r
个1
s 的那些。
$allBinary = array(); // the array of binary numbers
for ($i = 0; $i <= $max; $i++)
if (substr_count(decbin($i), "1") >= $r) // we count the number of ones to determine if they are >= $r
// we make the length of the binary numbers equal to the number of elements in the array,
// so that it is easy to select elements from the array, based on which of the digits are 1.
// we do this by padding zeros to the left.
$temp = str_pad(decbin($i), $n, "0", STR_PAD_LEFT);
$allBinary[] = $temp;
然后,我们使用与上述相同的技巧为我们的组合选择元素。我相信 cmets 已经足够解释了。
$combs = array(); // the array for all the combinations.
$row = array(); // the array of binary digits in one element of the $allBinary array.
foreach ($allBinary as $key => $one)
$combs[$key] = "";
$row = str_split($one); // we store the digits of the binary number individually
foreach ($row as $indx => $digit)
if ($digit == '1') // if the digit is 1, then the corresponding element in the array is part of this combination.
$combs[$key] .= $a[$indx]; // add the array element at the corresponding index to the combination
就是这样。你完成了!
如果你有类似的东西
echo count($combs);
那么它会给你29
。
补充说明:
我是在看到您的问题后才阅读的,作为一个新手,我发现这些很有用:
*** - http://en.wikipedia.org/wiki/Combination Php recursion to get all possibilities of strings Algorithm to return all combinations of k elements from n此外,这里有一些文档的快速链接,应该可以帮助将来看到此内容的人:
http://php.net/manual/en/function.decbin.php http://php.net/manual/en/function.bindec.php http://php.net/manual/en/function.str-pad.php【讨论】:
你能解释一下你所说的 $r 是每个组合中元素的最小数量吗? 这个想法是用最少的$r
元素生成所有可能的组合。换句话说,我们想要包含$r
或更多元素的组合。希望说明清楚吗?【参考方案3】:
function arrToBit(Array $element)
$bit = '';
foreach ($element as $e)
$bit .= '1';
$length = count($element);
$num = bindec($bit);
$back = [];
while ($num)
$back[] = str_pad(decbin($num), $length, '0', STR_PAD_LEFT);
$num--;
//$back[] = str_pad(decbin(0), $length, '0', STR_PAD_LEFT);
return $back;
function bitToArr(Array $element, $bit)
$num = count($element);
$back = [];
for ($i = 0; $i < $num; $i++)
if (substr($bit, $i, 1) == '1')
$back[] = $element[$i];
return $back;
$tags = ['a', 'b', 'c'];
$bits = arrToBit($tags);
$combination = [];
foreach ($bits as $b)
$combination[] = bitToArr($tags, $b);
var_dump($combination);
【讨论】:
【参考方案4】:$arr = array(1,2,3,4,5,6);
$check_value =[];
$all_values = [];
CONT:
$result = $check_value;
shuffle($arr);
$check_value = array_slice($arr,0,3);
if(count($check_value) == 3 && serialize($check_value) !== serialize($result))
$result = $check_value;
array_push($all_values,$result);
goto CONT;
print_r($all_values);
【讨论】:
我们也可以通过GOTO或者递归来实现 Goto is evil.以上是关于求一个PHP计算数组内元素的不同组合,请看案例的主要内容,如果未能解决你的问题,请参考以下文章