如何在PHP中生成多个数组中的所有项组合

如何在PHP中生成多个数组中的所有项组合,php,arrays,combinations,iteration,Php,Arrays,Combinations,Iteration,我正在尝试在几个数组中查找所有项的组合。 阵列的数量是随机的(可以是2、3、4、5…)。 每个数组中的元素数也是随机的 例如,我有3个数组: $arrayA = array('A1','A2','A3'); $arrayB = array('B1','B2','B3'); $arrayC = array('C1','C2'); 我想生成一个包含3 x 3 x 2=18个组合的数组: A1、B1、C1 A1、B1、C2 A1、B2、C1 A1、B2、C2 A1、B3、C1 A1、B3、C2 A

我正在尝试在几个数组中查找所有项的组合。 阵列的数量是随机的(可以是2、3、4、5…)。 每个数组中的元素数也是随机的

例如,我有3个数组:

$arrayA = array('A1','A2','A3');
$arrayB = array('B1','B2','B3');
$arrayC = array('C1','C2');
我想生成一个包含3 x 3 x 2=18个组合的数组:

  • A1、B1、C1
  • A1、B1、C2
  • A1、B2、C1
  • A1、B2、C2
  • A1、B3、C1
  • A1、B3、C2
  • A2、B1、C1
  • A2、B1、C2

问题是创建一个具有可变数量源数组的函数…

以下是递归解决方案:

function combinations($arrays, $i = 0) {
    if (!isset($arrays[$i])) {
        return array();
    }
    if ($i == count($arrays) - 1) {
        return $arrays[$i];
    }

    // get combinations from subsequent arrays
    $tmp = combinations($arrays, $i + 1);

    $result = array();

    // concat each array from tmp with each element from $arrays[$i]
    foreach ($arrays[$i] as $v) {
        foreach ($tmp as $t) {
            $result[] = is_array($t) ? 
                array_merge(array($v), $t) :
                array($v, $t);
        }
    }

    return $result;
}

print_r(
    combinations(
        array(
            array('A1','A2','A3'), 
            array('B1','B2','B3'), 
            array('C1','C2')
        )
    )
);

这是笛卡尔积,我只是。这是你的电话号码

函数数组\u笛卡尔乘积($array)
{
$result=array();
$arrays=数组值($arrays);
$sizeIn=sizeof($arrays);
$size=$sizeIn>0?1:0;
foreach($array作为$array)
$size=$size*sizeof($array);
对于($i=0;$i<$size;$i++)
{
$result[$i]=array();
对于($j=0;$j<$sizeIn;$j++)
数组推送($result[$i],current($arrays[$j]);
对于($j=($sizeIn-1);$j>=0;$j--)
{
if(下一个($arrays[$j]))
打破
elseif(isset($arrays[$j]))
重置($arrays[$j]);
}
}
返回$result;
}

此代码除了简单之外,还可以获取多个数组的所有组合并保留键

function get_combinations($arrays) {
    $result = array(array());
    foreach ($arrays as $property => $property_values) {
        $tmp = array();
        foreach ($result as $result_item) {
            foreach ($property_values as $property_key => $property_value) {
                $tmp[] = $result_item + array($property_key => $property_value);
            }
        }
        $result = $tmp;
    }
    return $result;
}
示例:

Array
(
    Array
    (
        '1' => 'White',
        '2' => 'Green',
        '3' => 'Blue'
    ),
    Array
    (
        '4' =>' Small',
        '5' => 'Big'
    )
)
Array
(
    [0] => Array
    (
        [1] => White
        [4] =>  Small
    )
    [1] => Array
    (
        [1] => White
        [5] => Big
    )
    [2] => Array
    (
        [2] => Green
        [4] =>  Small
    )
    [3] => Array
    (
        [2] => Green
        [5] => Big
    )
    [4] => Array
    (
        [3] => Blue
        [4] =>  Small
    )
    [5] => Array
    (
        [3] => Blue
        [5] => Big
    )
)
将返回:

Array
(
    Array
    (
        '1' => 'White',
        '2' => 'Green',
        '3' => 'Blue'
    ),
    Array
    (
        '4' =>' Small',
        '5' => 'Big'
    )
)
Array
(
    [0] => Array
    (
        [1] => White
        [4] =>  Small
    )
    [1] => Array
    (
        [1] => White
        [5] => Big
    )
    [2] => Array
    (
        [2] => Green
        [4] =>  Small
    )
    [3] => Array
    (
        [2] => Green
        [5] => Big
    )
    [4] => Array
    (
        [3] => Blue
        [4] =>  Small
    )
    [5] => Array
    (
        [3] => Blue
        [5] => Big
    )
)

我知道这个问题很老,但我今天也遇到了同样的问题,决定尝试一下新的发电机:

function generateCombinations(array $array) {
    foreach (array_pop($array) as $value) {
        if (count($array)) {
            foreach (generateCombinations($array) as $combination) {
                yield array_merge([$value], $combination);
            };
        } else {
            yield [$value];
        }
    }
}

foreach (generateCombinations(['a' => ['A'], 'b' => ['B'], 'c' => ['C', 'D'], 'd' => ['E', 'F', 'G']]) as $c) {
        var_dump($c);
    }
结果:

array(4) {
[0]=>
string(1) "E"
[1]=>
string(1) "C"
[2]=>
string(1) "B"
[3]=>
string(1) "A"
}
array(4) {
[0]=>
string(1) "E"
[1]=>
string(1) "D"
[2]=>
string(1) "B"
[3]=>
string(1) "A"
}
array(4) {
[0]=>
string(1) "F"
[1]=>
string(1) "C"
[2]=>
string(1) "B"
[3]=>
string(1) "A"
}
array(4) {
[0]=>
string(1) "F"
[1]=>
string(1) "D"
[2]=>
string(1) "B"
[3]=>
string(1) "A"
}
array(4) {
[0]=>
string(1) "G"
[1]=>
string(1) "C"
[2]=>
string(1) "B"
[3]=>
string(1) "A"
}
array(4) {
[0]=>
string(1) "G"
[1]=>
string(1) "D"
[2]=>
string(1) "B"
[3]=>
string(1) "A"
}
还有一个想法:

$ar = [
    'a' => [1,2,3],
    'b' => [4,5,6],
    'c' => [7,8,9]
];

$counts = array_map("count", $ar);
$total = array_product($counts);
$res = [];

$combinations = [];
$curCombs = $total;

foreach ($ar as $field => $vals) {
    $curCombs = $curCombs / $counts[$field];
    $combinations[$field] = $curCombs;
}

for ($i = 0; $i < $total; $i++) {
    foreach ($ar as $field => $vals) {
        $res[$i][$field] = $vals[($i / $combinations[$field]) % $counts[$field]];
    }
}

var_dump($res);
$ar=[
'a'=>[1,2,3],
“b”=>[4,5,6],
'c'=>[7,8,9]
];
$counts=数组映射(“count”、$ar);
$total=阵列产品($counts);
$res=[];
$组合=[];
$curCombs=$total;
foreach($ar as$字段=>$VAL){
$curCombs=$curCombs/$counts[$field];
$combinations[$field]=$curCombs;
}
对于($i=0;$i<$total;$i++){
foreach($ar as$字段=>$VAL){
$res[$i][$field]=$vals[($i/$combines[$field])%$counts[$field]];
}
}
var_dump($res);
我喜欢这个解决方案: 但为了回答实际问题(假设每个组合的元素数量应等于传入阵列的数量),应修改函数:

function getCombinations(...$arrays)
    {
        $result = [[]];
        foreach ($arrays as $property => $property_values) {
            $tmp = [];
            foreach ($result as $result_item) {
                foreach ($property_values as $property_value) {
                    $tmp[] = array_merge($result_item, [$property => $property_value]);
                }
            }
            $result = $tmp;
        }
        return $result;
    }
用法:

$arrayA = array('A1','A2','A3');
$arrayB = array('B1','B2','B3');
$arrayC = array('C1','C2');

print_r(getCombinations($arrayA, $arrayB, $arrayC));
结果是:

Array
(
    [0] => Array
        (
            [0] => A1
            [1] => B1
            [2] => C1
        )

    [1] => Array
        (
            [0] => A1
            [1] => B1
            [2] => C2
        )

    [2] => Array
        (
            [0] => A1
            [1] => B2
            [2] => C1
        )

    [3] => Array
        (
            [0] => A1
            [1] => B2
            [2] => C2
        )

    [4] => Array
        (
            [0] => A1
            [1] => B3
            [2] => C1
        )

    [5] => Array
        (
            [0] => A1
            [1] => B3
            [2] => C2
        )

    [6] => Array
        (
            [0] => A2
            [1] => B1
            [2] => C1
        )

    [7] => Array
        (
            [0] => A2
            [1] => B1
            [2] => C2
        )

    [8] => Array
        (
            [0] => A2
            [1] => B2
            [2] => C1
        )

    [9] => Array
        (
            [0] => A2
            [1] => B2
            [2] => C2
        )

    [10] => Array
        (
            [0] => A2
            [1] => B3
            [2] => C1
        )

    [11] => Array
        (
            [0] => A2
            [1] => B3
            [2] => C2
        )

    [12] => Array
        (
            [0] => A3
            [1] => B1
            [2] => C1
        )

    [13] => Array
        (
            [0] => A3
            [1] => B1
            [2] => C2
        )

    [14] => Array
        (
            [0] => A3
            [1] => B2
            [2] => C1
        )

    [15] => Array
        (
            [0] => A3
            [1] => B2
            [2] => C2
        )

    [16] => Array
        (
            [0] => A3
            [1] => B3
            [2] => C1
        )

    [17] => Array
        (
            [0] => A3
            [1] => B3
            [2] => C2
        )

)
我从O'Relly()那里得到这个

那就用,

$set = array('A', 'B', 'C');
$power_set = pc_array_power_set($set);

那就应该成功了

下面是一个代码,它从一组数字生成唯一的组合

如果你有一个数字列表,比如
1,3,4,7,12
,你可以生成一组
X
数字,它们都是唯一的,没有重复的

第一个函数适用于
PHP7.4
或更高版本,第二个函数使用键存储值。基于基准,这两种方法都非常有效

函数get_combos74($map,$size,&$generated=[],$loop=1,$i=0,$prefix=[]))
{
如果($loop==1){
排序($map);
}
对于(;$i
我改进了@mr1031011给出的解决方案,允许可选地保存密钥

/**
 * Generate an array of permutations from a given array[array[options]]
 * e.g.
 * ['foo' => [null, 'a'], 'bar' => ['b']]
 *
 * will generate:
 * [null, 'b']
 * ['a', 'b']
 *
 * or with preserveKeys = true:
 * ['foo' => null,'bar' => 'b']
 * ['foo' => 'a','bar' => 'b']
 *
 * @param array $array
 * @param bool  $preserveKeys
 *
 * @return Generator
 */
function generatePermutations(array $array, bool $preserveKeys = false): Generator
{
    if ($preserveKeys) {
        end($array);
        $key = key($array);
    }

    foreach (array_pop($array) as $value) {
        $item = isset($key) ? [$key => $value] : [$value];

        if (!count($array)) {
            yield $item;
            continue;
        }

        foreach (generatePermutations($array, $preserveKeys) as $combination) {
            yield array_merge($item, $combination);
        }
    }
}

您总是希望每个数组中有一个元素?如果我想要重复数组的唯一组合,我应该如何更改此函数?例如,如果我有数组('A1','A2','A3'),数组('A1','A2','A3'),数组('C1','C2'),我想要的结果是“A1,A2,C1”,“A1,A3,C1”,等等,但没有“A1,A1,C1”?另外(如果我没有问太多;),{“A1”,“A2”,“C1”}这和{“A2”,“A1”,“C1”}是一样的,所以我只想要一个组合?@AlexAngelico-对于其他有同样问题的人,请看array_unique,保存了我的a[…]到PHP网站的链接显然没有任何关于这个函数的线索。你能举一个调用它的例子吗?这个函数处理同一个数组所花费的时间是Lolo函数的2.5倍。不知道为什么其他人对此不屑一顾。这个解决方案非常适合我,并且像我希望的那样保留了数组键+1该解决方案对我来说非常有效,必须稍微调整以组合多个关联数组。当顺序无关紧要时,它是一个组合。当顺序确实重要时,它是一种排列。在这种情况下,这是一种排列,而不是组合。这是最简单的解决方案。有没有办法做到这一点<代码>数组(4){'d'=>string(1)“E”'c'=>string(1)“c”'b'=>string(1)“b”'a'=>string(1)“a”}我的问题的解决方法:创建这样的数组
['a'=>['key'=>a','value'=>a'],['key'=>a','value'=>n']]
很棒,似乎是一个更准确的解决方案-我与Luna的答案有些不一致