Finding cartesian product with PHP associative arrays

前端 未结 10 2090
醉梦人生
醉梦人生 2020-11-22 04:17

Say that I have an array like the following:

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


        
10条回答
  •  借酒劲吻你
    2020-11-22 04:40

    If memory consumption is important or you don't need all the combinations in the end you could use an iterator to generate one combination at a time. If you need all the combinations you can use iterator_to_array.

    function cartezianIterator($inputArray)
    {
        $maximumPosition = array_map('count', $inputArray);
        $position = array_pad([], count($inputArray), 0);
    
        while (false !== ($item = buildItemAtPosition($inputArray, $position))) {
    
            yield $item;
    
            $position = incrementPosition($position, $maximumPosition);
        }
    }
    
    function buildItemAtPosition($inputArray, $positions)
    {
        if ($positions[0] >= count($inputArray[0])) {
            return false;
        }
    
        $item = [];
        foreach ($inputArray as $rowIndex => $row) {
            $position = $positions[$rowIndex];
    
            $item[] = $row[$position];
        }
    
        return $item;
    }
    
    function incrementPosition($position, $maximumPosition)
    {
        $digitToIncrement = count($position) - 1;
    
        do {
            $position[$digitToIncrement]++;
    
            if ($position[$digitToIncrement] < $maximumPosition[$digitToIncrement] || 0 === $digitToIncrement) {
                //no overflow
                break;
            }
    
            //overflow, reset to zero and increment parent digit
            $position[$digitToIncrement] = 0;
    
            $digitToIncrement--;
        } while ($digitToIncrement >= 0);
    
        return $position;
    }
    

    Then, to get one solution at a time you could use a foreach or next, like this:

    $iterator = cartezianIterator($inputArray);
    
    //of course, you need to do something with the result...
    $combination = next($iterator);
    $combination = next($iterator);
    $combination = next($iterator);
    $combination = next($iterator);
    $combination = next($iterator);
    $combination = next($iterator);
    

    This solution is very very fast if you need only a few combinations. Also, the memory consumption is very low (it uses a flat array to store some integers).

    Note: recursive functions are not used.

提交回复
热议问题