skip to Main Content

I’ve been banging my head against this problem for a while. I feel like it should be simple, but I’m having a hard time coming up with a solution.

I’m looking to pre-populate a database, and I need to create SQL statements with some foreign key values. It would be tedious to hand-code them, so naturally I decided to do it in code.

What I want are series of arrays that have values as such:

[1]
[2]
[3]
[1,1]
[1,2]
[1,3]
[2,1]
[2,2]
...
[1,1,1]
[1,1,2]
[1,1,3]
...
[3,1,1]
...
[3,3,3]

I want to specify the number of values in the array, and the numerical value at which it causes the preceeding value to roll over.

In the example I gave above, it would be like generate(3,3), since the maximum number of elements is 3, and the highest value is 3.

How could I write some code that would give me this series of arrays?

2

Answers


  1. This is a recursive function that will generate each of the combinations of the ranges up to the maximum value, with elements in each array from 1 to the number specified:

    function generate($elements, $maxvalue) {
        if ($elements == 0) return array();
        $result = array();
        foreach (range(1, $maxvalue) as $el) {
            $result[] = array($el);
        }
        foreach (range(1, $maxvalue) as $el) {
            foreach (generate($elements - 1, $maxvalue) as $arr) {
                $result[] = array($el, ...$arr);
            }
        }
        return $result;
    }
    
    $combs = generate(3, 3);
    

    Output is too long to show here but can be seen in this demo on 3v4l.org

    Note for PHP < 7.4, replace

    $result[] = array($el, ...$arr);
    

    with

    $result[] = array_merge(array($el), $arr);
    
    Login or Signup to reply.
  2. Here’s a version using generators (which may be slightly easier on memory than pure arrays):

    function generate(int $elementsCount, int $maxValue, array $current = []): Generator
    {
        for ($value = 1; $value <= $maxValue; $value++) {
            yield [...$current, $value];
        }
        if ($elementsCount > 1) {
            for ($value = 1; $value <= $maxValue; $value++) {
                yield from generate($elementsCount - 1, $maxValue, [...$current, $value]);
            }
        }
    }
    

    Exemple usage + debug/print:

    $combinations = generate(3, 3);
    print_r(iterator_to_array($combinations, false));
    

    Demo

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search