如何在PHP中生成多个数组中的所有项组合
我正在尝试在几个数组中查找所有项的组合。 阵列的数量是随机的(可以是2、3、4、5…)。 每个数组中的元素数也是随机的 例如,我有3个数组:如何在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
$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的答案有些不一致