如何使用 PHP 中每个子数组的一个值生成所有可能的组合?

How to generate all possible combinations using one value from each sub-array in PHP?

我有一个看似简单的任务,但我被卡住了。我尝试了重组和迭代器,但没有任何想法让我印象深刻。他们说一张图片胜过一千个字,所以我将展示我的 'picture' 示例数组:

array (size=4)
  0 =>
    array (size=4)
      0 => int 1
      1 => int 2
      2 => int 3
      3 => int 4
  1 =>
    array (size=3)
      0 => string 'a' (length=1)
      1 => string 'b' (length=1)
      2 => string 'c' (length=1)
  2 =>
    array (size=3)
      0 => string 'X' (length=1)
      1 => string 'Y' (length=1)
      2 => string 'Z' (length=1)
  3 =>
    array (size=5)
      0 => string '!' (length=1)
      1 => string '"' (length=1)
      2 => string '#' (length=1)
      3 => string '$' (length=1)
      4 => string '%' (length=1)

规则:

  1. 数组大小和子数组大小是随机的,而且相当大。
  2. 只能使用任何子数组中的一个值。
  3. 结果应从最短字符串到最长字符串排序。
  4. 必须是内存高效的,由于正在生成大量数据,结果应该存储/离线比较,如文件或 mysql 数据库。但是一次一个。

所需字符串组合的示例:

1
2
3
4
a
b
c
X ...
1a
1b
1c
2a
2b ...
aX!
aX" ...
1aX!
1aX" .......
4cZ%

我尝试了几个迭代器,比如 How to generate in PHP all combinations of items in multiple arrays

在我的例子中,解决方案是这个递归函数,我将 $combine 变量切换为首先从数组中插入单个值,然后将合并设置为 true,以合并数据库中的所有值(除了包含当前迭代值的那些):

            function iterdb( $arrays, $i = 0, $combine = false ) {
                if ( ! isset( array_keys( $arrays )[ $i ] ) ) {
                    return false;
                }
                if ( $i == 0 && $combine === true ) {
                    //Adding empty option to obtain all combos
                    for ( $x = 0; $x < count( $arrays ); $x ++ ) {
                        $arrays[ $x ][] = preg_replace( '`=[^\&]+`', '=', $arrays[ $x ][0] );
                    }
                }

                $this->iterdb( $arrays, $i + 1, $combine );//Call iteration on each following array
                $transactions = array();
                sort( $arrays[ $i ] );
                $this->log( 'Iterating array ' . $i . ' using combine ' . ( $combine ? 'True' : 'False' ) );
                foreach ( $arrays[ array_keys( $arrays )[ $i ] ] as $v ) {
                    if ( $this->counter > 0 ) {
                        if ( $combine === false ) {
                            $transactions[] = "INSERT IGNORE INTO scout_queries (scout,query) VALUES ('" . $this->Class . "','$v')";
                        } else {
                            $tmp = $this->queries->find( array(
                                'scout = :scout and query NOT LIKE :query',
                                ':scout' => $this->Class,
                                ':query' => '%' . ( array_values( explode( '=', $v ) )[0] ) . '%'
                            ), array( 'order' => 'CHAR_LENGTH(query) DESC' ) );

                            foreach ( $tmp as $t ) {
                                $transactions[] = "INSERT IGNORE INTO scout_queries (scout,query) VALUES ('" . $this->Class . "','" . $t->query . "&$v')";
                                $transactions   = $this->saveTransactions( $transactions );
                            }
                        }

                    }
                    $transactions = $this->saveTransactions( $transactions, true );
                }


                if ( $i == 0 && $combine === false ) {
                    return $this->iterdb( $arrays, 0, true );
                }
            }