3

假设一个数组是

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

我想通过提供具有以下排列的两个参数(两个数组)来调用一个函数-

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...

当然,实际的数组会更大。

4

3 回答 3

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)

示例性实现(作为 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);
    }
}

我希望这很有用。

另一种与数组相关的算法:用模数排序(仅供参考,在写这个时我被提醒到那个矩阵的东西)

于 2012-04-13T19:00:52.047 回答
1

如何将 array_pop 与 array_merge 一起使用

查一下这个网址

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

并将 sarafov 的建议与 url 一起使用

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

就像是

foreach($combinations as $combination)
    while(in_array($combination)){
        $arr = array_pop($combination);
        foo($fruit , $combination); 
    }
}
于 2012-04-13T17:47:12.027 回答
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)));
于 2012-04-13T17:51:05.457 回答