Комбинации всех элементов подмассива без повторов

У меня есть «атрибуты» из базы данных. Каждый атрибут имеет много значений. Теперь я хочу смешать эти значения для создания уникальных комбинаций.

пример ввода:

$a = array(
35=>array('green','red','brown'),
36=>array('fox','house','dog')
);

вывод — все возможные комбинации элементов второго измерения. Пример вывода ниже:

$output = array(
array(35=>'green',36=>'fox'),
array(35=>'green',36=>'house'),
array(35=>'green',36=>'dog'),
array(35=>'red',36=>'fox'),
array(35=>'red',36=>'house'),
array(35=>'red',36=>'dog'),
array(35=>'brown',36=>'fox'),
array(35=>'brown',36=>'house'),
array(35=>'brown',36=>'dog'),
);

моя функция без повторений:

function myfunction($a){

$keys = array_keys($a);
$result = array();

if(count($keys)==0){
$result = array();
}
elseif(count($keys)==1){
$k = $keys[0];
foreach($a[$k] as $v){
$result[] = array($k=>$v);
}
}
elseif(count($keys)==2){
$k1 = $keys[0];
$k2 = $keys[1];
foreach($a[$k1] as $v1){
foreach($a[$k2] as $v2){
$result[] = array($k1=>$v1,$k2=>$v2);
}
}
}
elseif(count($keys)==3){
$k1 = $keys[0];
$k2 = $keys[1];
$k3 = $keys[2];
foreach($a[$k1] as $v1){
foreach($a[$k2] as $v2){
foreach($a[$k3] as $v3){
$result[] = array($k1=>$v1,$k2=>$v2,$k3=>$v3);
}
}
}
}
else{
throw new Exception('To much keys', 1);
}

return $result;
}

1

Решение

Это должно работать для вас:

Так что же делает этот код?

1. Сколько существует комбинаций?

Итак, сначала вопрос, сколько комбинаций существует, и ответ на этот вопрос: вы должны умножить количество каждого массива друг на друга.

Итак (с = сумма1):

смассив 1 * смассив 2 * … * смассив n

И конкретно для вашего примера:

смассив 1 * смассив 2 знак равно 3 * 3 знак равно 9

*1 И если вам интересно, почему я выбрал c на сумму, из-за функции count() в php

2. Получение всех комбинаций

Как мы теперь получим все комбинации с длиной суммы всех массивов?

Ну, довольно просто, мы просто перебираем все комбинации (в начале просто пустая комбинация ([] == array())), который у нас уже есть со следующим массивом, пока мы не получим желаемую длину, которую мы хотим, в этом случае последнюю итерацию последнего массива.

Итак, в качестве примера:

Array with the elements (Empty array is '[]'):

[
[1, 2],
[3, 4]
]

                               //new combinations for the next iteration
|
array NAN*:

Combinations:
- []         |  -> []
|
array 1 [1,2]:       -------------
|             |
Combinations:   v             v
- []    + 1  |  -> [1]
- []    + 2  |  -> [2]
|
array 2 [3,4]:       -------------
|             |
Combinations:   v             v
- []    + 3  |  -> [3]
- []    + 4  |  -> [4]
- [1]   + 3  |  -> [1,3]
- [1]   + 4  |  -> [1,4]
- [2]   + 3  |  -> [2,3]
- [2]   + 4  |  -> [2,4]
//^ All combinations here

* NAN: не номер

Итак, как вы можете видеть в приведенном выше примере, у нас теперь есть все комбинации с длиной количества всех массивов, которые у нас есть.

Но чтобы получить только комбинации с желаемой длиной, мы перезаписываем массив результатов каждую итерацию, чтобы в конце в массиве результатов были только комбинации с ожидаемой длиной.

код:

<?php

$data = [
35 => ["green", "red", "brown"],
36 => ["fox", "house", "dog"]
];

$combinations = [[]];
$comKeys = array_keys($data);for ($count = 0; $count < count($comKeys); $count++) {
$tmp = [];
foreach ($combinations as $v1) {
foreach ($data[$comKeys[$count]] as $v2)
$tmp[] = $v1 + [$comKeys[$count] => $v2];

}
$combinations = $tmp;
}

print_r($combinations);

?>

выход:

Array
(
[0] => Array
(
[35] => green
[36] => fox
)

[1] => Array
(
[35] => green
[36] => house
)

[2] => Array
(
[35] => green
[36] => dog
)

[3] => Array
(
[35] => red
[36] => fox
)

[4] => Array
(
[35] => red
[36] => house
)

[5] => Array
(
[35] => red
[36] => dog
)

[6] => Array
(
[35] => brown
[36] => fox
)

[7] => Array
(
[35] => brown
[36] => house
)

[8] => Array
(
[35] => brown
[36] => dog
)

)
3

Другие решения

Вы можете использовать это: https://gist.github.com/jwage/11193216

или же

используйте код ниже:

<?php
$attributes = [
[
'P', 'M', 'G', 'XG'
],
[
'Vermelho', 'Amarelo', 'Verde'
],
];function array_mix($leftItems, $rightItems)
{
$results   = [];
foreach ($leftItems as $leftItem) {
foreach ($rightItems as $key => $rightItem) {
$results[] = array_merge((array) $leftItem, (array) $rightItem);
}
}
return $results;
}

$y = $attributes[0];

foreach($attributes as $key => $attrs) {
if(isset($attributes[$key + 1]) && is_array($attributes[$key + 1])) {
$y = array_mix($y, $attributes[$key + 1]);
}
}

var_dump($y);
0

По вопросам рекламы [email protected]