Skip to content

Instantly share code, notes, and snippets.

@cecilemuller
Created February 1, 2013 03:13
Show Gist options
  • Star 76 You must be signed in to star a gist
  • Fork 18 You must be signed in to fork a gist
  • Save cecilemuller/4688876 to your computer and use it in GitHub Desktop.
Save cecilemuller/4688876 to your computer and use it in GitHub Desktop.
PHP: Get all combinations of multiple arrays (preserves keys)
<?php
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_value) {
$tmp[] = array_merge($result_item, array($property => $property_value));
}
}
$result = $tmp;
}
return $result;
}
$combinations = get_combinations(
array(
'item1' => array('A', 'B'),
'item2' => array('C', 'D'),
'item3' => array('E', 'F'),
)
);
var_dump($combinations);
?>
array (size=8)
0 =>
array (size=3)
'item1' => string 'A' (length=1)
'item2' => string 'C' (length=1)
'item3' => string 'E' (length=1)
1 =>
array (size=3)
'item1' => string 'A' (length=1)
'item2' => string 'C' (length=1)
'item3' => string 'F' (length=1)
2 =>
array (size=3)
'item1' => string 'A' (length=1)
'item2' => string 'D' (length=1)
'item3' => string 'E' (length=1)
3 =>
array (size=3)
'item1' => string 'A' (length=1)
'item2' => string 'D' (length=1)
'item3' => string 'F' (length=1)
4 =>
array (size=3)
'item1' => string 'B' (length=1)
'item2' => string 'C' (length=1)
'item3' => string 'E' (length=1)
5 =>
array (size=3)
'item1' => string 'B' (length=1)
'item2' => string 'C' (length=1)
'item3' => string 'F' (length=1)
6 =>
array (size=3)
'item1' => string 'B' (length=1)
'item2' => string 'D' (length=1)
'item3' => string 'E' (length=1)
7 =>
array (size=3)
'item1' => string 'B' (length=1)
'item2' => string 'D' (length=1)
'item3' => string 'F' (length=1)
@Ultimater
Copy link

Ultimater commented Jan 5, 2023

Here's a PHP version of dernoun's Java solution.

function getNumberOfOptions(array $arr): void {
    $n = count($arr);
    $indices = array_fill(0, $n, 0);
    while(true) {

        // grab current combination for the indices.
        for($i = 0; $i < $n; $i++) {
            echo $arr[$i][$indices[$i]] . ' ';
        }
        echo "\n";

        // Find the rightmost array that has more
        // elements left after the current element
        // in that array
        $next = $n - 1;
        while($next >= 0 &&
            ($indices[$next] + 1 >=
            count($arr[$next]))
        ) {
            $next--;
        }

        // No such array is found so no more
        // combinations left
        if ($next < 0)
            break;

        // If found move to next element in that
        // array
        $indices[$next]++;

        // For all arrays to the right of this
        // array current index again points to
        // first element
        for($i = $next + 1; $i < $n; $i++) {
            $indices[$i] = 0;
        }
    }
}

Or if we change the function to instead return the array of combinations rather than print them, it would look like this:

function get_combinations(array $arrays): array {
    $n = count($arrays);
    $indices = array_fill(0, $n, 0);
    $combinations = [];
    while(true) {

        // grab current combination for the indices.
        $combination = [];
        for($i = 0; $i < $n; $i++) {
            $combination[] = $arrays[$i][$indices[$i]];
        }
        $combinations[] = $combination;

        // Find the rightmost array that has more
        // elements left after the current element
        // in that array
        $next = $n - 1;
        while($next >= 0 && 
                ($indices[$next] + 1 >=
                count($arrays[$next]))
        ) {
            $next--;
        }

        // No such array is found so no more
        // combinations left
        if ($next < 0)
            break;

        // If found move to next element in that
        // array
        $indices[$next]++;

        // For all arrays to the right of this
        // array current index again points to
        // first element
        for($i = $next + 1; $i < $n; $i++) {
            $indices[$i] = 0;
        }
    }
    return $combinations;
}

@fofopp
Copy link

fofopp commented Nov 8, 2023

Thanks! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment