从混合阵列中获取所有可能的结果

时间:2012-05-20 21:20:06

标签: php

我到处寻找这个,但无法完全找到它。 (我的PHP和数学技能让我失望了...) 我有一个包含例如三个字符串的数组(也可能更多!)(例如:“a”,“b”,“c”)。现在我想创建一个返回所有可能性的函数。我到处寻找并找到了一些很好的函数,他们以一切可能的方式移动了数组,但是他们并没有逐个删除一个值。所以他们有:

  

abc acb bac bca cab cba

哪个好,但是我需要一个将它提升到一个新水平的功能:

  

abc acb bac bca cab cba ac ca ab ba bc ba a b c

并且这无论多少值(让我们说最多10)。 整个晚上我一直在努力解决这个问题,有人能让我摆脱困境并为我解决这个谜题吗?或者给出一些建议。 感谢

3 个答案:

答案 0 :(得分:1)

看起来你要求的是“电源组”。功率集包括空集,我不包括。

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

我认为从技术上讲,这不是一个权力集,因为我在比较集合时假设订单很重要。反正...

答案 1 :(得分:1)

与往常一样,以自己的方式解决问题会更有趣。您可以更轻松地修改代码以满足您的特殊需求,因为您知道自己在做什么:) 请参阅下面的测试脚本:

<?

$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";                                         

?>

我只是回应了预期的输出,你可以添加一个结果数组,但那是你的一部分:)

输出:

[] //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

答案 2 :(得分:0)

在O'Reilly的PHP Cookbook, section 4.26上有一个排列的示例函数。它只创建固定大小的排列,但可以在循环中使用来处理任何大小,就像你需要它一样。

代码

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

输出

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