3

配列が

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

次の順列で2つのパラメーター(両方の配列)を提供して関数を呼び出したい-

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

これがあなたに必要なものだと思います。

コード:

<?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 に答える
1

array_mergeでarray_popを使用するのはどうですか

このURLをチェック

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

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 に答える