代码之家  ›  专栏  ›  技术社区  ›  NVG

PHP数组组合

  •  22
  • NVG  · 技术社区  · 14 年前

    我有一个由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)

    我不知道从哪里开始。 你能帮助我吗?

    6 回复  |  直到 14 年前
        1
  •  39
  •   Galen    12 年前

    你可以用这里找到的解决办法 http://stereofrog.com/blok/on/070910

    万一链接断了这是密码。。。。

    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, ' ';
    

    12345 12346 12347 12356 12357 12367 12456 12457 12467 12567 13456 13457 13467 13567 14567 23456 23457 23467 23567 24567 34567

        2
  •  19
  •   Samsquanch Dinesh    7 年前
    <?php
    
    echo "<pre>";
    $test = array("test_1","test_2","test_3");
    
    // Get Combination
    $return = uniqueCombination($test);
    
    //Sort
    sort($return);
    
    //Pretty Print
    print_r(array_map(function($v){ return implode(",", $v); }, $return));
    
    function uniqueCombination($in, $minLength = 1, $max = 2000) {
        $count = count($in);
        $members = pow(2, $count);
        $return = array();
        for($i = 0; $i < $members; $i ++) {
            $b = sprintf("%0" . $count . "b", $i);
            $out = array();
            for($j = 0; $j < $count; $j ++) {
                $b{$j} == '1' and $out[] = $in[$j];
            }
    
            count($out) >= $minLength && count($out) <= $max and $return[] = $out;
            }
        return $return;
    }
    
    ?>
    

    Array
    (
        [0] => test_1
        [1] => test_2
        [2] => test_3
        [3] => test_1,test_2
        [4] => test_1,test_3
        [5] => test_2,test_3
        [6] => test_1,test_2,test_3
    )
    
        3
  •  14
  •   Ömer An    6 年前

    这个 Math_Combinatorics 在PEAR存储库中,您完全可以执行以下操作:

    返回所有组合和排列的包, 重复 ,具有给定的集合和子集大小。关联数组是 保存。

    require_once 'Math/Combinatorics.php';
    $combinatorics = new Math_Combinatorics;
    
    $input = array(1, 2, 3, 4, 5, 6, 7);
    $output = $combinatorics->combinations($input, 5); // 5 is the subset size
    
    // 1,2,3,4,5
    // 1,2,3,4,6
    // 1,2,3,4,7
    // 1,2,3,5,6
    // 1,2,3,5,7
    // 1,2,3,6,7
    // 1,2,4,5,6
    // 1,2,4,5,7
    // 1,2,4,6,7
    // 1,2,5,6,7
    // 1,3,4,5,6
    // 1,3,4,5,7
    // 1,3,4,6,7
    // 1,3,5,6,7
    // 1,4,5,6,7
    // 2,3,4,5,6
    // 2,3,4,5,7
    // 2,3,4,6,7
    // 2,3,5,6,7
    // 2,4,5,6,7
    // 3,4,5,6,7
    
        4
  •  1
  •   Nguyễn Văn Vinh    6 年前

    希望这能帮助别人。

    具体内容:

    function _combine($numbers, $length)
    {
        $combinations = array();
        $stack = array();
    
        // every combinations can be ordered
        sort($numbers);
    
        // startup
        array_push($stack, array(
            'store' => array(),
            'options' => $numbers,
        ));
    
        while (true) {
            // pop a item
            $item = array_pop($stack);
    
            // end of stack
            if (!$item) {
                break;
            }
    
            // valid store
            if ($length <= count($item['store'])) {
                $combinations[] = $item['store'];
                continue;
            }
    
            // bypass when options are not enough
            if (count($item['store']) + count($item['options']) < $length) {
                continue;
            }
    
            foreach ($item['options'] as $index => $n) {
                $newStore = $item['store'];
                $newStore[] = $n;
    
                // every combine can be ordered
                // so accept only options which is greater than store numbers
                $newOptions = array_slice($item['options'], $index + 1);
    
                // push new items
                array_push($stack, array(
                    'store' => $newStore,
                    'options' => $newOptions,
                ));
            }
        }
    
        return $combinations;
    }
    
        5
  •  1
  •   Prince Dorcis    4 年前

    answer

    function uniqueCombination($values, $minLength = 1, $maxLength = 2000) {
        $count = count($values);
        $size = pow(2, $count);
        $keys = array_keys($values);
        $return = [];
    
        for($i = 0; $i < $size; $i ++) {
            $b = sprintf("%0" . $count . "b", $i);
            $out = [];
    
            for($j = 0; $j < $count; $j ++) {
                if ($b[$j] == '1') {
                    $out[$keys[$j]] = $values[$keys[$j]];
                }
            }
    
            if (count($out) >= $minLength && count($out) <= $maxLength) {
                 $return[] = $out;
            }
        }
    
        return $return;
    }
    

    如:

    print_r(uniqueCombination([
        'a' => 'xyz',
        'b' => 'pqr',
    ]);
    

    结果:

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

    它仍然适用于非关联数组:

    print_r(uniqueCombination(['a', 'b']);
    

    结果:

    Array
    (
        [0] => Array
            (
                [1] => b
            )
    
        [1] => Array
            (
                [0] => a
            )
    
        [2] => Array
            (
                [0] => a
                [1] => b
            )
    
    )
    
        6
  •  0
  •   Nguyễn Văn Vinh    5 年前

    优化组合算法速度和内存的新方案

    心态:生成K个数的组合。新的解决方案将使用K'for'语句。一个“换”一个号码。

    $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);
                    }
                }
            }
        }
    }
    

    以及生成将由eval()函数执行的实际代码的代码的详细信息

    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);
    }
    

    $k = 5;
    $array = array(1, 2, 3, 4, 5, 6, 7);
    $callback = function ($record) {
        echo implode($record) . "\n";
    };
    combine($array, $k, $callback);