如何使用选项生成多个数组的所有唯一组合?

时间:2016-10-04 20:48:49

标签: php arrays combinations

我想将多个数组中的所有值组合在一起以创建独特的组合。有一个问题:一些数组可以是可选的。

例如:我正在配置PC,我可以选择:

  • 5种机箱(包括风扇,PSU和主板)
  • 5种类型的磁盘(可选)
  • 5种类型的内存(可选)
  • 5种视频卡(可选)

如您所见,结果可以是任何组合:

  1. 机箱类型1,磁盘类型3,内存类型5,视频卡类型1
  2. 机箱类型1,磁盘类型3,内存类型5,视频卡类型2
  3. 机箱类型1,磁盘类型3,内存类型5,视频卡类型3
  4. 机箱类型1,无磁盘,内存类型5,视频卡类型2
  5. 机箱类型1,无磁盘,内存类型5,无视频卡
  6. 机箱类型1,无磁盘,无内存,无视频卡
  7. 要确定一系列产品是否可选,'optional' => [0|1]部分已包含在数组中: - )

    以下数组是' production'中使用的数组的摘录。应该合并:

    array(
        array('optional' => 0, 0, 1),
        array('optional' => 0, 3, 4),
        array('optional' => 0, 6, 7, 8),
        array('optional' => 1, 6, 7, 8, 2),
        array('optional' => 1, 6, 7, 8, 5, 9),
        array('optional' => 1, 6, 7, 8, 10, 11, 12)
    )
    

    输出应该是这样的:

    0, 3, 6
    0, 3, 7
    0, 3, 8
    0, 4, 6
    0, 4, 7
    0, 4, 8
    1, 3, 6
    1, 3, 7
    1, 3, 8
    [...]
    0, 3, 6, 2  <-- outcome with an optional product from the 4th array
    0, 3, 7, 9  <-- outcome with an optional product from the 5th array
    0, 3, 8, 12 <-- outcome with an optional product from the 6th array
    

    如您所见,上面的数组被合并为一个数组。一些子数组是必需的,其中optional是0,或者optional是可选的。

    在有可选阵列之前,我使用了以下功能:

    <?PHP
    function generateCombinations(array $array) {
        foreach (array_pop($array) as $value) {
            if (count($array)) {
                foreach (generateCombinations($array) as $combination) {
                    yield array_merge([$value], $combination);
                };
            } else {
                yield [$value];
            }
        }
    }
    ?>
    

    通过以下方式使用:

    foreach ( generateCombinations($ArrCombinateMe) as $combination ){
        // Some code here
    }
    

    该功能完美运行所以我想使用类似的东西,并且确切地说我不想丢失生成器功能,因为它实际上是内存友好的(我之前的函数会在返回可用输出之前将所有内容组合在一起,这只会返回在4GB内存中有320万个组合。这个功能在千万次测试中已经超过了320万。

    目前我还希望包含可选数组,以便生成这些数组: - )

    请注意:我喜欢速度但是对于这个功能而言,这并不重要,因为它将在没有任何用户交互的情况下作为后台工作运行。

    我希望有人可以帮助我: - )

1 个答案:

答案 0 :(得分:0)

似乎答案比理解问题简单得多。 您无需更改过程 - 只需在可选数组中包含'null'作为可能的值。这意味着该部分不包括在内。

这样会返回返回null值的数组,但它们的索引将代表source。以下面的数组为例:

$data = array(
    'Chassis'   => array(0, 1, 2),
    'Mainboard' => array(3, 4, 5),
    'PSU'       => array(6, 7, 8),
    'Disk'      => array(null, 9, 10),
    'GFX'       => array(null, 11, 12),
    'Memory'    => array(null, 13, 14, 15)
);

其中一个结果是:[0,3,6,null,11,null] *表示包含了GFX。

如果您不想使用

的空值,则可以过滤该结果
array_filter($combination, 'is_int')
只需正确处理'is_int'

0 param。如果0不是有效ID,那么您可以跳过它(并且可以使用0而不是null)

*)由于array_merge() args order

,实际上最后一个元素跳转到第一个位置

编辑:

这个发生器本身的速度提高约35%(内存使用量相同),并且不需要过滤,整体速度提高两倍:

function generateCombinations(array $array) {
    foreach (array_pop($array) as $id) {
        if (empty($array)) {
            yield isset($id) ? [$id] : [];
            continue;
        }

        foreach (generateCombinations($array) as $combination) {
            if (isset($id)) { $combination[] = $id; }
            yield $combination;
        }
    }
}