4

I have to make a complex array with other array values.

The original array is:

Array (
     [0] => Array (
        [0] => A
        [1] => B
        [2] => C
    )

    [1] => Array (
        [0] => D
        [1] => E
        [2] => F
    )
)

I'm looking for a function which give me all combinations values possible, like this:

Array (
  [0] => Array (A, D),
  [1] => Array (A, E),
  [2] => Array (A, F),
  [3] => Array (B, D),
  [4] => Array (B, E),
  [5] => Array (B, F),
  [6] => Array (C, D),
  [7] => Array (C, E),
  [8] => Array (C, F)
)

Of course, this algo must work even if the numbers of values in the original array are different.

I'm looking for a simple function in PHP documentation for doing this, but I did not find one.

I've Googled it with keywords like "multiplex" or "combine" but with no luck. I think the best way is to make a recursive function, but I can't find the correct algo.

Andrew Barber
  • 39,603
  • 20
  • 94
  • 123
  • 1
    basically you want a cartesian result. here is a link for a similiar example http://stackoverflow.com/questions/6311779/finding-cartesian-product-with-php-associative-arrays – Naved Munshi Dec 18 '14 at 12:45
  • will you be constantly having 3 values in the child array?? – Ronser Dec 18 '14 at 12:49
  • hi, and tks for your answer. No, my original array could have X entries with arrays – Neteor Informatique Dec 18 '14 at 12:50
  • You could take all the elements from the sub-arrays and create a temporary array with all the elements, and use my answer at http://stackoverflow.com/a/27177761/3186769 to find all 2-element combinations. Does that help? – pradeepcep Dec 18 '14 at 13:13

4 Answers4

3

A simple recursive function to calculate cartesian product:

function cartesian(array $data)
{
    function cartesian_r(array $data, array $path, &$out)
    {
        if (count($data) > 1) {
            // recursive step
            $head = array_slice($data, 0, -1);
            $tail = end($data);
            foreach ($tail as $item) {
                cartesian_r($head, array_merge($path, [$item]), $out);
            }
        } else {
            // unwind step
            foreach ($data[0] as $item) {
                $out[] = array_merge([$item], $path);
            }
        }
    }

    $out = [];
    cartesian_r($data, [], $out);

    return $out;
}

$out = cartesian([['A', 'B'], ['C', 'D'], ['E', 'F']]);

print_r($out);

Output

Array
(
    [0] => Array
        (
            [0] => A
            [1] => E
            [2] => C
        )

    [1] => Array
        (
            [0] => B
            [1] => E
            [2] => C
        )

    [2] => Array
        (
            [0] => A
            [1] => E
            [2] => D
        )

    [3] => Array
        (
            [0] => B
            [1] => E
            [2] => D
        )

    [4] => Array
        (
            [0] => A
            [1] => F
            [2] => C
        )

    [5] => Array
        (
            [0] => B
            [1] => F
            [2] => C
        )

    [6] => Array
        (
            [0] => A
            [1] => F
            [2] => D
        )

    [7] => Array
        (
            [0] => B
            [1] => F
            [2] => D
        )

)
Ja͢ck
  • 170,779
  • 38
  • 263
  • 309
2

Just two foreach

$first = array('A', 'B', 'C', 'D');
$second = array('E', 'F', 'G');

$result = array();
foreach ($first as $f) {
    foreach ($second as $s) {
        $result[] = array($f, $s);
    }
}
var_dump($result);
vaso123
  • 12,347
  • 4
  • 34
  • 64
1

This works for as many sub_arrays as you wont .. it is not ordered as the original output but this can be easily fixed with a sort function as in the example:

 $input = array(
    0 => array ('A','B','C'),
    1 => array ('D','E','F'),
    2 => array ('X','Y','Z'),
    /*...*/
);

$result = array();  
foreach($input as $sub_arr){
    $_result = array();
    foreach($sub_arr as $val){
        if($result){
            foreach($result as $old){
                $old[] = $val;
                $_result[] = $old;
            }
        }else{ 
            $_result[] = array($val);
        }
    }
    $result = $_result;
} 
array_multisort($result); //sort all layers alphabetically.
echo "<pre>";
print_r($result);

Working example: Fiddle

d.raev
  • 9,216
  • 8
  • 58
  • 79
0

This is the simplest dynamic thing i could imagine :

It displays "ALL COMBINATIONS POSSIBLE"

<?php

$origArray = array(
    array(
         "A",
         "B",
         "C"        
    ),
     array(
        "D",
        "E",
        "F"     
    )
);

$endArray = array();

foreach ($origArray as $key_1 => $value_1){
    foreach ($origArray as $key_2 => $value_2){
        if($key_1 == $key_2){
            continue;
        }
        foreach($value_1 as $key_1_1 => $value_1_1 ){
            foreach ($value_2 as $key_2_1 => $value_2_1){
                $endArray[] = array($value_1_1, $value_2_1);
            }
        }


    }

}
echo "<pre>";
var_dump($endArray);
echo "</pre>";

If you want to dispaly all combinations of the firts sub-array you could use:

<?php

$origArray = array(
    array(
         "A",
         "B",
         "C"        
    ),
     array(
        "D",
        "E",
        "F"     
    )
);

$endArray = array();

foreach ($origArray as $key_1 => $value_1){
    foreach($origArray[0] as $key_1_1 => $value_1_1 ){
        if($key_1 == 0 ){
            continue;
        }
        foreach ($value_1 as $key_2_1 => $value_2_1){

            $endArray[] = array($value_1_1, $value_2_1);
        }
    }
}
echo "<pre>";
var_dump($endArray);
echo "</pre>";
Alexis Peters
  • 1,583
  • 1
  • 10
  • 17