Как найти все возможные комбинации массивов в PHP

$data = array(
'a' => array('a1', 'a2', 'a3'),
'b' => array('b1', 'b2', 'b3', 'b4'),
'c' => array('c1', 'c2', 'c3', 'c4', 'c5'));

чтобы получить

a1
a2
a3
b1
b2
b3
b4
c1
c2
c3
c4
c5

a1 b1
a1 b2
a1 b3
a1 b4
a1 c1
a1 c2
a1 c3
a1 c4
a1 c5

b1 c1
b1 c2
b1 c3
b1 c4
b1 c5
b2 c1
b2 c2
b2 c3
b2 c4
b2 c5
b3 c1
b3 c2
b3 c3
b3 c4
b3 c5
b4 c1
b4 c2
b4 c3
b4 c4
b4 c5

a1 b1 c1
a1 b1 c2
a1 b1 c3
a1 b1 c4
a1 b1 c5
a1 b2 c1
a1 b2 c2
a1 b2 c3
a1 b2 c4
a1 b2 c5
a1 b3 c1
a1 b3 c2
a1 b3 c3
a1 b3 c4
a1 b3 c5
a1 b4 c1
a1 b4 c2
a1 b4 c3
a1 b4 c4
a1 b4 c5
etc...

Спасибо


person DenverZ    schedule 28.12.2010    source источник
comment
Этот вопрос еще менее ясен, чем ваш недавний вопрос о Perl, который ОЧЕНЬ похож на этот. Вы должны действительно немного уточнить, что именно вы хотите сделать!   -  person canavanin    schedule 29.12.2010
comment
Почему вы задаете один и тот же вопрос для двух языков? Своего рода обман: stackoverflow. ком/вопросы/4549529/   -  person jwueller    schedule 29.12.2010
comment
Это должно работать как отправная точка: stackoverflow. com/questions/2516599/   -  person sberry    schedule 29.12.2010
comment
Это называется перестановками — упрощает гугление. См.: stereofrog.com/blok/on/070816.   -  person troelskn    schedule 29.12.2010


Ответы (2)


Очевидно, вы хотите построить декартово произведение нескольких массивов, то есть каждый элемент в сочетании с другим элементом.

Кроме того, вы хотите иметь кортежи результатов, которые пропускают один или несколько из этих массивов, которые для простоты я бы смоделировал как имеющие элемент null в каждом из этих массивов:

$result = array(array()); // We need to start with one element already, because thats the identity element of the cartesian product
foreach ($data as $arr)
{
    array_push($arr,null); // Add a null element to the array to get tuples with less than all arrays

    // This is the cartesian product:
    $new_result = array();
    foreach ($result as $old_element)
        foreach ($arr as $el)
            $new_result []= array_merge($old_element,array($el));
    $result = $new_result;
}

Обратите внимание, что для строки результата a1 b3 c2 этот код дает вам array('a1','b3','c2'), а для строки результата b4 c3 этот код дает вам array('b4','c3',null).

person AndreKR    schedule 28.12.2010
comment
Спасибо, этот алгоритм также спас мой день @AndreKR с марта: D - person ZenithS; 09.02.2017

Если вы хотите распечатать их все, просто используйте циклы:

foreach($data['a'] as $k1 =>$v1){
    $output[]=$v1;
    foreach($data['b'] as $k2 => $v2){
        $output[]=$v2;
        $output[]=$v1."-".$v2;
        foreach($data['c'] as $k3 => $v3){
            $output[]=$v3;
            $output[]=$v1."-".$v2."-".$v3;
        }
    }
} 

http://www.webdeveloper.com/forum/showthread.php?t=168409

Гугл в этом плане прекрасен...

Если вы хотите увидеть, сколько существует возможностей, умножьте их:

$count1=1;
$count2=1;
for each $data as $item{
$count2*=count($item);
}
person J V    schedule 28.12.2010
comment
Любой способ сделать это с помощью рекурсивной функции? - person Oli; 29.12.2010
comment
@Oli: я мог бы сделать это на python, но я никогда не работал с объектами на php (это намного лучше, как процедурный язык). Также следует отметить, что я пропустил там строку ... вам понадобится еще одна для $v2."-".$v3, так что я думаю, это было бы очень сложно сделать в рекурсивной функции (отсюда встроенная функция list.product() python) - person J V; 29.12.2010