我试图找到几个数组中所有项目的组合。 数组的数量是随机的(可以是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种组合的数组:
问题是创建一个具有可变数量的源数组的函数......
答案 0 :(得分:55)
这是递归解决方案:
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')
)
)
);
答案 1 :(得分:13)
这是一个笛卡尔积,我只是asked the same question not too long ago。这是algorithm that is posted on the PHP website。
function array_cartesian_product($arrays)
{
$result = array();
$arrays = array_values($arrays);
$sizeIn = sizeof($arrays);
$size = $sizeIn > 0 ? 1 : 0;
foreach ($arrays as $array)
$size = $size * sizeof($array);
for ($i = 0; $i < $size; $i ++)
{
$result[$i] = array();
for ($j = 0; $j < $sizeIn; $j ++)
array_push($result[$i], current($arrays[$j]));
for ($j = ($sizeIn -1); $j >= 0; $j --)
{
if (next($arrays[$j]))
break;
elseif (isset ($arrays[$j]))
reset($arrays[$j]);
}
}
return $result;
}
答案 2 :(得分:5)
此代码除了简单之外,还可以获取多个数组的所有组合并保留密钥。
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
)
)
答案 3 :(得分:4)
我知道这个问题已经过时了,但今天我遇到了同样的问题并决定尝试新的发电机:
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"
}
答案 4 :(得分:4)
我喜欢这种解决方案: https://stackoverflow.com/a/33259643/3163536 但是要回答实际的问题(假设每个组合的元素数应等于传入数组的数量),则应修改函数:
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
)
)
答案 5 :(得分:3)
还有一个想法:
$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);
答案 6 :(得分:1)
这是一个从一组数字生成唯一组合的代码。
如果您有一组数字,例如1,3,4,7,12
,则可以生成X
个数字集,这些数字都是唯一的,没有重复。
第一个函数在PHP 7.4
或更高版本中起作用,第二个函数使用键存储值。两者都基于基准运行良好。
function get_combos74($map, $size, &$generated = [], $loop = 1, $i = 0, $prefix = [])
{
if ($loop == 1) {
sort($map);
}
for (; $i < count($map); $i++) {
if ($loop < $size) {
get_combos74($map, $size, $generated, $loop + 1, $i + 1, [...$prefix, $map[$i]]);
} else {
$generated[] = [...$prefix, $map[$i]];
}
}
return $generated;
}
function get_combosSTR($map, $size, &$generated = [], $loop = 1, $i = 0, $prefix = '')
{
if ($loop == 1) {
sort($map);
}
for (; $i < count($map); $i++) {
if ($loop < $size) {
get_combosSTR($map, $size, $generated, $loop + 1, $i + 1, "$prefix{$map[$i]}:");
} else {
$generated["$prefix{$map[$i]}"] = 0;
}
}
return $generated;
}
答案 7 :(得分:0)
我改进了@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);
}
}
}
答案 8 :(得分:-1)
我是从O'Relly(https://www.oreilly.com/library/view/php-cookbook/1565926811/ch04s25.html)那里得到的,
function pc_array_power_set($array) {
// initialize by adding the empty set
$results = array(array( ));
foreach ($array as $element)
foreach ($results as $combination)
array_push($results, array_merge(array($element), $combination));
return $results;
}
然后使用
对其进行调用$set = array('A', 'B', 'C');
$power_set = pc_array_power_set($set);
那应该可以解决问题!