tags:

views:

69

answers:

5

I have the following PHP code which works out the possible combinations from a set of arrays:

function showCombinations($string, $traits, $i){

    if($i >= count($traits)){

        echo trim($string) . '<br>';

    }else{

        foreach($traits[$i] as $trait){
            showCombinations("$string$trait", $traits, $i + 1);
        }

    }

}

$traits = array(
            array('1','2'),
            array('1','2','3'),
            array('1','2','3')
            );

showCombinations('', $traits, 0);

However, my problem is that I need to store the results in an array for processing later rather than just print them out but I can't see how this can be done without using a global variable.

Does anyone know of an alternative way to achieve something similar or modify this to give me results I can use?

A: 

store the results in a $_SESSION variable.

dnagirl
+3  A: 

Return them. Make showCombinations() return a list of items. In the first case you only return one item, in the other recursive case you return a list with all the returned lists merged. For example:

function showCombinations(...) {
    $result = array();
    if (...) {
        $result[] = $item;
    }
    else {
        foreach (...) {
            $result = array_merge($result, showCombinations(...));
        }
    }
    return $result;
}
Lukáš Lalinský
Thanks for this, I was having a bit of a mental block yesterday - really quick as well!
Tom
A: 

Using the variable scope modifier static could work. Alternatively, you could employ references, but that's just one more variable to pass. This works with "return syntax".

function showCombinations($string, $traits, $i){
    static $finalTraits;
    if (!is_array($finalTraits)) {
        $finalTraits = array();
    }
    if($i >= count($traits)){

        //echo trim($string) . '<br>';
        $finalTraits[] = $string;

    } else {

        foreach($traits[$i] as $trait){
            showCombinations("$string$trait", $traits, $i + 1);
        }

    }
    return $finalTraits;
}

$traits = array(
            array('1','2'),
            array('1','2','3'),
            array('1','2','3')
            );

echo join("<br>\n",showCombinations('', $traits, 0));

Of course, this will work as expected exactly once, before the static nature of the variable catches up with you. Therefore, this is probably a better solution:

function showCombinations($string, $traits, $i){
    $finalTraits = array();
    if($i >= count($traits)){
        $finalTraits[] = $string;
    } else {
        foreach($traits[$i] as $trait){
            $finalTraits = array_merge(
                               $finalTraits,
                               showCombinations("$string$trait", $traits, $i + 1)
                               );
        }
    }
    return $finalTraits;
}
Dereleased
Would be fun to debug if you call the function multiple times.
Lukáš Lalinský
Point already addressed.
Dereleased
+1  A: 

In addition to the other answers, you could pass the address of an array around inside your function, but honestly this isn't nearly the best way to do it.

agscala
A: 

although the solution by Lukáš is the purest as it has no side effects, it may be ineffective on large inputs, because it forces the engine to constantly generate new arrays. There are two more ways that seem to be less memory-consuming

  • have a results array passed by reference and replace the echo call with $result[]=
  • (preferred) wrap the whole story into a class and use $this->result when appropriate

the class approach is especially nice when used together with php iterators

stereofrog