如果你想知道类似这样的东西如何运作,这就是我使用二进制实现它且不使用任何PHP库的方法。
function search_get_combos($query){
$list = explode(" ", $query);
$bits = count($list); //bits of binary number equal to number of words in query;
//Convert decimal number to binary with set number of bits, and split into array
$dec = 1;
$binary = str_split(str_pad(decbin($dec), $bits, '0', STR_PAD_LEFT));
while($dec < pow(2, $bits)) {
//Each 'word' is linked to a bit of the binary number.
//Whenever the bit is '1' its added to the current term.
$curterm = "";
$i = 0;
while($i < ($bits)){
if($binary[$i] == 1) {
$curterm .= $list[$i]." ";
}
$i++;
}
$terms[] = $curterm;
//Count up by 1
$dec++;
$binary = str_split(str_pad(decbin($dec), $bits, '0', STR_PAD_LEFT));
}
return $terms;
}
请注意,这将仅返回唯一组合,但可以轻松扩展以获取每个可能的组合顺序,因此在您的示例中,这将输出:
Array
(
[0] => fish
[1] => dog
[2] => dog fish
[3] => cat
[4] => cat fish
[5] => cat dog
[6] => cat dog fish
)
编辑(更多澄清)
基本理论
首先,二进制数如您所知是由一串 1 和 0 组成的。该数字的长度指其具有的“位”数,例如数字 011001
具有6个位(如果您感兴趣,这个数字代表25)。然后,如果数字的每个位对应于其中一个术语,每次计数时,如果该位为1,则将该术语包含在输出中,而如果为0,则忽略该项。因此,这就是正在发生的基本原理。
深入了解代码
PHP 没有二进制计数的方法,但可以将十进制转换为二进制。因此,此函数实际上是使用十进制进行计数,并将其转换为二进制。但是,由于位数很重要,因为每个术语都需要自己的位,所以您需要添加前导零,这就是此部分所做的工作:str_pad(decbin($dec), $bits, '0', STR_PAD_LEFT)
现在,此函数使用 while 循环,但由于它需要循环的次数取决于有多少个术语,因此需要进行一些数学计算。如果您曾经使用过二进制,您将知道可以制造的最大数字是 2^n(其中n是位数)。
我认为这应该涵盖了函数的所有混淆部分,如果我漏掉了什么,请告诉我。
查看正在发生的情况
使用以下代码输出所使用的逻辑,可能更容易理解!
function search_get_combos_demo($query){
$list = explode(" ", $query);
$bits = count($list);
$dec = 1;
while($dec < pow(2, $bits)) {
$binary = str_split(str_pad(decbin($dec), $bits, '0', STR_PAD_LEFT));
$curterm = "";
$i = 0;
while($i < ($bits)){
if($binary[$i] == 1) {
$curterm[] = $list[$i]." ";
}
$i++;
}
echo "Iteration: $dec <table cellpadding=\"5\" border=\"1\"><tr>";
foreach($binary as $b){
echo "<td>$b</td>";
}
echo "</tr><tr>";
foreach($list as $l){
echo "<td>$l</td>";
}
echo "</tr></table>Output: ";
foreach($curterm as $c){
echo $c." ";
}
echo "<br><br>";
$terms[] = $curterm;
$dec++;
}
return $terms;
}