Get ALL possible results from mixing array

后端 未结 3 585
独厮守ぢ
独厮守ぢ 2021-01-13 02:01

I\'ve looked everywhere for this online, but couldn\'t completely find it. (my PHP and math skills are letting my down for this one...) I have an array containing for exampl

相关标签:
3条回答
  • 2021-01-13 02:14

    It looks like you're asking for the "power set". the power set includes the empty set, which i wont include.

    require_once 'Math/Combinatorics.php';
    $set = range('a', 'c');
    $permutationSizes = range(1, count($set));
    $combinatorics = new Math_Combinatorics;
    $result = array();
    foreach ($permutationSizes as $permutationSize) {
        $result = array_merge($result, $combinatorics->permutations($set, $permutationSize));
    }
    print_r($result);
    

    http://pear.php.net/package/Math_Combinatorics

    I guess technically this isnt a power set because i'm assuming order matters when comparing sets. anyway...

    0 讨论(0)
  • 2021-01-13 02:23

    As always, it's much more fun to solve the problem your own way. You can modify your code to fit your special needs much easier then, because you know what you are doing :) See my test script below:

    <?
    
    $a = array("a", "b", "c");
    
    function getAll($prefix, $remaining)
    {
        echo $prefix."\n";
    
        if (count($remaining) == 0) return;
        if (count($remaining) == 1)
        {                                                                
            echo $prefix.$remaining[0]."\n";
            return;                                                      
        }                                                                
    
        for ($i = 0; $i < count($remaining); $i++)                       
        {                                                                
            $t = $remaining;                                             
            unset($t[$i]);                                               
            $t = array_values($t);                                       
            getAll($prefix.$remaining[$i], $t);              
        }                                                                                                       
    }                                                        
    echo "<pre>\n";                                          
    getAll('', $a);                                          
    echo "</pre>\n";                                         
    
    ?>
    

    I just echo'd the intended output, you could add up a result array instead, but that's your part :)

    Output:

    [] //empty value is included, but blank lines won't show up here, so I wrote []
    a
    ab
    abc
    ac
    acb
    b
    ba
    bac
    bc
    bca
    c
    ca
    cab
    cb
    cba
    
    0 讨论(0)
  • 2021-01-13 02:27

    There's an example function for permutations on O'Reilly's PHP Cookbook, section 4.26. It only creates permutations of a fixed size, but can be used in a loop to deal with any size like you need it.

    Code

    function pc_next_permutation($p, $size) {
        // slide down the array looking for where we're smaller than the next guy
        for ($i = $size - 1; $p[$i] >= $p[$i+1]; --$i) { }
    
        // if this doesn't occur, we've finished our permutations
        // the array is reversed: (1, 2, 3, 4) => (4, 3, 2, 1)
        if ($i == -1) { return false; }
    
        // slide down the array looking for a bigger number than what we found before
        for ($j = $size; $p[$j] <= $p[$i]; --$j) { }
    
        // swap them
        $tmp = $p[$i]; $p[$i] = $p[$j]; $p[$j] = $tmp;
    
        // now reverse the elements in between by swapping the ends
        for (++$i, $j = $size; $i < $j; ++$i, --$j) {
             $tmp = $p[$i]; $p[$i] = $p[$j]; $p[$j] = $tmp;
        }
        return $p;
    }
    
    $set = explode(' ', 'a b c');
    
    // $all will contain the final output
    $all = $set;
    while(count($set) > 1) {
        $perms = array();
        $size = count($set) - 1;
        $perm = range(0, $size);
        $j = 0;
    
        do { 
             foreach ($perm as $i) { $perms[$j][] = $set[$i]; }
        } while ($perm = pc_next_permutation($perm, $size) and ++$j);
    
        foreach ($perms as $p) {
             $all[] = implode(' ', $p);
        }
        array_pop($set);    
    }
    
    // display results
    foreach($all as $each) {
        echo $each . "\n";
    }
    

    Output

    a
    b
    c
    a b c
    a c b
    b a c
    b c a
    c a b
    c b a
    a b
    b a
    

    Live example

    0 讨论(0)
提交回复
热议问题