数组中值的排列

时间:2012-04-13 16:50:23

标签: php arrays combinations combinatorics

假设数组是

Array
(
    [0] => 1
    [1] => 2
    [2] => 3
    [3] => 4
)

我想通过提供两个params(两个数组)以及以下排列来调用函数 -

array(1) and array(2,3,4)
array(1,2) and array(3,4)
array(1,2,3) and array (4)
array(1,3) and array(2,4)
array(1,4) and array(2,3)
array(2) and array(1,3,4)
and so on...

当然实际的阵列会更大。

3 个答案:

答案 0 :(得分:2)

我不知道如何调用“置换”(它甚至可能不是排列),但是我很有希望利用集合中的元素是有序的这一事实(如果没有,则有顺序)索引,所以使用索引而不是值)所以从右向左移动并将所有左右组合。

这可能是递归或堆栈,我通常更喜欢堆栈。

建议的用法(封装函数调用):

$funky = function($a, $b) {
    printf("(%s) and (%s)\n", implode(',', $a), implode(',', $b));
};

$paired = function($function) {
    return function(array $array) use ($function) {
        ...
    };
};


$funkyAll = $paired($funky);
$funkyAll(range(1, 5));

使用已排序(需要更多内存)堆栈消耗策略运行此命令会提供以下输出(按列格式化):

(1) and (2,3,4,5)    (2,4) and (1,3,5)    (1,4,5) and (2,3)
(2) and (1,3,4,5)    (2,5) and (1,3,4)    (2,3,4) and (1,5)
(3) and (1,2,4,5)    (3,4) and (1,2,5)    (2,3,5) and (1,4)
(4) and (1,2,3,5)    (3,5) and (1,2,4)    (2,4,5) and (1,3)
(5) and (1,2,3,4)    (4,5) and (1,2,3)    (3,4,5) and (1,2)
(1,2) and (3,4,5)    (1,2,3) and (4,5)    (1,2,3,4) and (5)
(1,3) and (2,4,5)    (1,2,4) and (3,5)    (1,2,3,5) and (4)
(1,4) and (2,3,5)    (1,2,5) and (3,4)    (1,2,4,5) and (3)
(1,5) and (2,3,4)    (1,3,4) and (2,5)    (1,3,4,5) and (2)
(2,3) and (1,4,5)    (1,3,5) and (2,4)    (2,3,4,5) and (1)

示例性实现(full source-code as gist)经过内存优化并生成此订单(array_pop而不是array_shift):

(1) and (2,3,4,5)    (2,4) and (1,3,5)    (1,4,5) and (2,3)
(2) and (1,3,4,5)    (2,5) and (1,3,4)    (1,3,4) and (2,5)
(3) and (1,2,4,5)    (2,4,5) and (1,3)    (1,3,5) and (2,4)
(4) and (1,2,3,5)    (2,3,4) and (1,5)    (1,3,4,5) and (2)
(5) and (1,2,3,4)    (2,3,5) and (1,4)    (1,2,3) and (4,5)
(4,5) and (1,2,3)    (2,3,4,5) and (1)    (1,2,4) and (3,5)
(3,4) and (1,2,5)    (1,2) and (3,4,5)    (1,2,5) and (3,4)
(3,5) and (1,2,4)    (1,3) and (2,4,5)    (1,2,4,5) and (3)
(3,4,5) and (1,2)    (1,4) and (2,3,5)    (1,2,3,4) and (5)
(2,3) and (1,4,5)    (1,5) and (2,3,4)    (1,2,3,5) and (4)

实现:

$stack[] = array(array(), $array);
while (list($left, $right) = array_pop($stack)) {
    $min = end($left);
    foreach ($right as $value)
    {
        if ($value < $min) continue;
        $left2 = array_merge($left, array($value));
        $right2 = array_diff($right, $left2);
        if (!($left2 && $count = count($right2))) continue;
        $function($left2, $right2);
        --$count && $stack[] = array($left2, $right2);
    }
}

我希望这很有用。

另一个与数组相关的算法:Sorting with a modulus(仅供参考,在写这篇文章时我被提醒那个矩阵的东西)

答案 1 :(得分:1)

如何将array_pop与array_merge一起使用

chk this url

http://php.net/manual/en/function.array-pop.php

并使用sarafov的建议与网址

http://www.sonyjose.in/blog/?p=62

类似

foreach($combinations as $combination)
    while(in_array($combination)){
        $arr = array_pop($combination);
        foo($fruit , $combination); 
    }
}

答案 2 :(得分:1)

我认为这就是你所需要的。

代码:

<?php

function combinations($arr, $n)
{
    $res = array();

    foreach ($arr[$n] as $item)
    {
        if ($n==count($arr)-1)
            $res[]=$item;
        else
        {
            $combs = combinations($arr,$n+1);

            foreach ($combs as $comb)
            {
                $res[] = "$item $comb";
            }
        }
    }
    return $res;
}

// Your ARRAY
//
// you can put as many items in each subarray as you like... 
// and as many subarrays as you like
$words = array(array('A','B'),array('C','D'), array('E','F'));

$combos = combinations($words,0);  // ALWAYS, call it with 0 as the last parameter
print_r($combos);

?>

输出

Array
(
    [0] => A C E
    [1] => A C F
    [2] => A D E
    [3] => A D F
    [4] => B C E
    [5] => B C F
    [6] => B D E
    [7] => B D F
)

用法:(如您的示例所示)

$combos = combinations(array(array(1,4),array(2,3)));