【问题标题】:Permutations of values in array数组中值的排列
【发布时间】:2012-04-13 16:50:23
【问题描述】:

假设一个数组是

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

当然实际的数组会更大。

【问题讨论】:

标签: php arrays combinations combinatorics


【解决方案1】:

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

这可以通过递归或堆栈实现,我通常更喜欢堆栈。

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

$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(仅供参考,写这个的时候我想起了那个矩阵的东西)

【解决方案2】:

如何使用 array_pop 和 array_merge

查看这个网址

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

并在 url 中使用 sarafov 的建议

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

类似

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

【讨论】:

    【解决方案3】:

    我想这就是你需要的。

    代码:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-28
      相关资源
      最近更新 更多