Search code examples
phparrayscombinationscartesian-productarray-merge

Get all combinations of one element from a dynamic amount of arrays


I want to merge every array value of an array with every array value of another array. Like so:

$a1 = ['a', 'b'];
$a2 = ['c', 'd', 'e', 'f'];
$a3 = ['g', 'h'];
$result = [];

foreach($a1 as $a) {
    foreach($a2 as $b) {
        foreach($a3 as $c) {
            $result[] = [$a, $b, $c];
        }
    }
}

The result should look like this:

array(16) {
  [0]=>
  array(3) {
    [0]=>
    string(1) "a"
    [1]=>
    string(1) "c"
    [2]=>
    string(1) "g"
  }
  [1]=>
  array(3) {
    [0]=>
    string(1) "a"
    [1]=>
    string(1) "c"
    [2]=>
    string(1) "h"
  }
  .... 
}

But I don't know how I can do it dynamically, because the number of arrays (e.g. $a1 - $a3) should be dynamically as well. So that I could merge for example $a1 - $a6 or $a1 - $a2, too.

I hope someone can help me. :)


Solution

  • Use the following recursive function for the cartesian product of a variable number of arrays:

    function array_cartesian_product(...$array)
    {
        if (empty($array)) return [[]];
    
        $column = array_shift($array);
        $cartesian = array_cartesian_product(...$array);
    
        $result = [];
        foreach ($column as $item) {
            foreach ($cartesian as $row) {
                array_unshift($row, $item);
                array_push($result, $row);
            }
        }
        return $result;        
    }
    
    // Usage:
    
    $a1 = ['a', 'b'];
    $a2 = ['c', 'd', 'e', 'f'];
    $a3 = ['g', 'h'];
    
    $result = array_cartesian_product($a1, $a2, $a3);
    
    print_r($result);
    
    $a = [ ['a', 'b'], ['c', 'd', 'e', 'f'], ['g', 'h'] ];
    
    $result = array_cartesian_product(...$a);
    
    print_r($result);