Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/267.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP数组组合_Php_Arrays_Combinations - Fatal编程技术网

PHP数组组合

PHP数组组合,php,arrays,combinations,Php,Arrays,Combinations,我有一个由7个数字组成的数组(1,2,3,4,5,6,7),我想从中选择5个数字,如 (1,2,3,4,5),(1,2,3,4,6),(1,2,3,4,7)。 请注意,(1,2,3,4,5)等于(4,5,3,1,2),因此输出中只应包括其中一个 我想知道PHP中是否有函数或任何算法可以做到这一点? 我不知道从哪里开始。 你能帮我吗 我希望将7个给定数字的所有组合(它们取自一个数组)放入5个插槽中,不考虑顺序。您可以使用此处找到的解决方案 如果链接断开,这是代码 class Combination

我有一个由7个数字组成的数组(1,2,3,4,5,6,7),我想从中选择5个数字,如
(1,2,3,4,5),(1,2,3,4,6),(1,2,3,4,7)。
请注意,(1,2,3,4,5)等于(4,5,3,1,2),因此输出中只应包括其中一个

我想知道PHP中是否有函数或任何算法可以做到这一点? 我不知道从哪里开始。 你能帮我吗


我希望将7个给定数字的所有组合(它们取自一个数组)放入5个插槽中,不考虑顺序。

您可以使用此处找到的解决方案

如果链接断开,这是代码

class Combinations implements Iterator
{
    protected $c = null;
    protected $s = null;
    protected $n = 0;
    protected $k = 0;
    protected $pos = 0;

    function __construct($s, $k) {
        if(is_array($s)) {
            $this->s = array_values($s);
            $this->n = count($this->s);
        } else {
            $this->s = (string) $s;
            $this->n = strlen($this->s);
        }
        $this->k = $k;
        $this->rewind();
    }
    function key() {
        return $this->pos;
    }
    function current() {
        $r = array();
        for($i = 0; $i < $this->k; $i++)
            $r[] = $this->s[$this->c[$i]];
        return is_array($this->s) ? $r : implode('', $r);
    }
    function next() {
        if($this->_next())
            $this->pos++;
        else
            $this->pos = -1;
    }
    function rewind() {
        $this->c = range(0, $this->k);
        $this->pos = 0;
    }
    function valid() {
        return $this->pos >= 0;
    }

    protected function _next() {
        $i = $this->k - 1;
        while ($i >= 0 && $this->c[$i] == $this->n - $this->k + $i)
            $i--;
        if($i < 0)
            return false;
        $this->c[$i]++;
        while($i++ < $this->k - 1)
            $this->c[$i] = $this->c[$i - 1] + 1;
        return true;
    }
}


foreach(new Combinations("1234567", 5) as $substring)
    echo $substring, ' ';
类组合实现迭代器
{
受保护的$c=null;
受保护的$s=null;
受保护的$n=0;
受保护$k=0;
受保护的$pos=0;
函数构造($s,$k){
if(is_数组($s)){
$this->s=array\u值($s);
$this->n=计数($this->s);
}否则{
$this->s=(字符串)$s;
$this->n=strlen($this->s);
}
$this->k=$k;
$this->revind();
}
函数键(){
返回$this->pos;
}
函数电流(){
$r=数组();
对于($i=0;$i<$this->k;$i++)
$r[]=$this->s[$this->c[$i]];
返回为数组($this->s)$r:内爆(“”,$r);
}
函数next(){
如果($this->_next())
$this->pos++;
其他的
$this->pos=-1;
}
函数倒带(){
$this->c=范围(0,$this->k);
$this->pos=0;
}
函数valid(){
返回$this->pos>=0;
}
受保护函数_next(){
$i=$this->k-1;
而($i>=0&&$this->c[$i]==$this->n-$this->k+$i)
$i--;
如果($i<0)
返回false;
$this->c[$i]++;
而($i++<$this->k-1)
$this->c[$i]=$this->c[$i-1]+1;
返回true;
}
}
foreach(新组合(“1234567”,5)作为$substring)
echo$substring';
12345 12346 12347 12356 12357 12367 12456 12457 12467 12567 13456 13457 13467 13567 14567 23456 23456 234567 23467 23567 24567 34567

梨内存储库完全满足您的需求:

返回所有组合和置换的包,不带 给定集合和子集大小的重复。关联数组是 保存


另一种基于堆栈的解决方案。它退出得很快,但会消耗很多内存

希望这能帮助别人

详细内容:

$total = count($array);
$i0 = -1;
for ($i1 = $i0 + 1; $i1 < $total; $i1++) {
    for ($i2 = $i1 + 1; $i2 < $total; $i2++) {
        for ($i3 = $i2 + 1; $i3 < $total; $i3++) {
            for ($i4 = $i3 + 1; $i4 < $total; $i4++) {
                for ($i5 = $i4 + 1; $i5 < $total; $i5++) {
                    $record = array();
                    for ($i = 1; $i <= $k; $i++) {
                        $t = "i$i";
                        $record[] = $array[$$t];
                    }
                    $callback($record);
                }
            }
        }
    }
}
函数_组合($number,$length)
{
$combines=array();
$stack=array();
//每个组合都可以订购
排序(数字);
//启动
数组\u推送($stack,array)(
'store'=>array(),
“选项”=>$number,
));
while(true){
//弹出一个项目
$item=array\u pop($stack);
//栈尾
如果(!$项目){
打破
}
//有效存储
如果($length$n){
$newStore=$item['store'];
$newStore[]=$n;
//每台联合收割机都可以订购
//因此,只接受大于存储编号的选项
$newOptions=array_slice($item['options',$index+1);
//推送新项目
数组\u推送($stack,array)(
'store'=>$newStore,
“选项”=>$newOptions,
));
}
}
返回$组合;
}

新的解决方案,优化了组合算法的速度和内存

心态:生成K个数字的组合。新的解决方案将使用K'for'语句。一个代表一个数字。 例如:$K=5表示使用了5个“for”语句

function combine($array, $k, $callback)
{
    $total = count($array);
    $init = '
        $i0 = -1;
    ';
    $sample = '
        for($i{current} = $i{previous} + 1; $i{current} < $total; $i{current}++ ) {
            {body}
        }
    ';

    $do = '
        $record = array();
        for ($i = 1; $i <= $k; $i++) {
            $t = "i$i";
            $record[] = $array[$$t];
        }
        $callback($record);
    ';
    $for = '';
    for ($i = $k; $i >= 1; $i--) {
        switch ($i) {
            case $k:
                $for = str_replace(['{current}', '{previous}', '{body}'], [$i, $i - 1, $do], $sample);
                break;
            case 1:
                $for = $init . str_replace(['{current}', '{previous}', '{body}'], [$i, $i - 1, $for], $sample);
                break;
            default:
                $for = str_replace(['{current}', '{previous}', '{body}'], [$i, $i - 1, $for], $sample);
                break;
        }
    }

    // execute
    eval($for);
}
改进了这一点,以使用关联数组:

函数唯一组合($values,$minLength=1,$maxLength=2000){
$count=计数($value);
$size=pow(2$count);
$keys=数组_键($values);
$return=[];
对于($i=0;$i<$size;$i++){
$b=sprintf(“%0”。$count.b”,$i);
$out=[];
对于($j=0;$j<$count;$j++){
如果($b[$j]=='1'){
$out[$keys[$j]]=$value[$keys[$j]];
}
}
如果(count($out)>=$minLength&&count($out)'xyz',
“b”=>“pqr”,
]);
结果:

Array
(
    [0] => Array
        (
            [1] => b
        )

    [1] => Array
        (
            [0] => a
        )

    [2] => Array
        (
            [0] => a
            [1] => b
        )

)
[
  [1,2,3,4], [1,2,3], [1,2,4], [1,3,4], [2,3,4], [1,2], [1,3], [1,4], [2,3], [2,4], [3,4], [1], [2], [3], [4]
]
它仍然适用于非关联阵列:

print_r(唯一组合(['a','b']);
结果:

Array
(
    [0] => Array
        (
            [1] => b
        )

    [1] => Array
        (
            [0] => a
        )

    [2] => Array
        (
            [0] => a
            [1] => b
        )

)
[
  [1,2,3,4], [1,2,3], [1,2,4], [1,3,4], [2,3,4], [1,2], [1,3], [1,4], [2,3], [2,4], [3,4], [1], [2], [3], [4]
]

我需要一个包含子集的组合函数,所以我接受了
@Nguyen Van Vinh
的答案,并根据我的需要对其进行了修改

如果将
[1,2,3,4]
传递给函数,它将返回每个唯一的组合和子集,排序如下:

下面是函数:

函数获取长度为($numbers,$length)的组合{
$result=array();
$stack=array();
//每个组合都可以订购
排序(数字);
//启动
数组\u推送($stack,array)(
'store'=>array(),
“选项”=>$number,
));
while(true){
//弹出一个项目
$item=array\u pop($stack);
//栈尾
如果(!$项目)中断;
//有效存储
如果($length$n){
$newStore=$item['store'];
$newStore[]=$n;
//每个联合收割机都可以订购,因此只接受大于存储编号的选项
$newOptions=array_slice($item['options',$i+1);
//数组\取消移位以进行数字排序,数组\推送以反转
数组\u取消移位($堆栈,数组(
'store'=>$newStore,
“选项”=>$newOptions,
));
}
}
返回$result;
}
函数get_all_组合($number){
$length=计数($number);
$result=[];
而($length>0){
$result=array_merge($result,get_compositions_with_length($numbers,$length));
$length--;
}
返回$result;
}
$numbers=[1,2,3,4];
$r
$k = 5;
$array = array(1, 2, 3, 4, 5, 6, 7);
$callback = function ($record) {
    echo implode($record) . "\n";
};
combine($array, $k, $callback);
Array
(
    [0] => Array
        (
            [b] => pqr
        )

    [1] => Array
        (
            [a] => xyz
        )

    [2] => Array
        (
            [a] => xyz
            [b] => pqr
        )

)
Array
(
    [0] => Array
        (
            [1] => b
        )

    [1] => Array
        (
            [0] => a
        )

    [2] => Array
        (
            [0] => a
            [1] => b
        )

)
[
  [1,2,3,4], [1,2,3], [1,2,4], [1,3,4], [2,3,4], [1,2], [1,3], [1,4], [2,3], [2,4], [3,4], [1], [2], [3], [4]
]