You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP求数组元素的不重复全组合问题求助

解决PHP数组生成无重复元素组合的问题

你遇到的核心问题是生成组合时没有限制元素的选取顺序,导致同一个元素集合的不同排列被多次生成——虽然你用了sort()和in_array()去重,但这种方式不仅效率低,还属于"事后补救"的冗余操作。我们可以从根本上避免重复组合的生成。

问题根源分析

你的递归函数每次都从数组的第0个元素开始遍历,比如生成2元素组合时,会先取PER_DAY再取PER_SIZE,也会取PER_SIZE再取PER_DAY——这两个组合的元素完全相同,只是顺序不同。正确的思路应该是让递归时只从当前元素的下一个位置开始选取元素,这样每个组合的元素都会按原数组顺序排列,自然不会产生重复。

修正后的代码

$arr = ['PER_DAY', 'PER_SIZE', 'PER_TYPE'];
$result = [];

function combinations($arr, $startIndex, $level, &$result, $curr=[]) {
    // 当需要的元素数量凑齐时,将当前组合加入结果
    if ($level == 0) {
        $result[] = $curr;
        return;
    }
    
    // 从startIndex开始遍历,避免回头选取已处理过的元素
    for ($i = $startIndex; $i < count($arr); $i++) {
        $newCurr = array_merge($curr, [$arr[$i]]);
        // 递归时起始索引更新为当前索引+1,层级减1
        combinations($arr, $i + 1, $level - 1, $result, $newCurr);
    }
}

// 生成1到数组长度的所有元素组合
for ($i = 1; $i <= count($arr); $i++) {
    combinations($arr, 0, $i, $result);
}

// 打印验证结果
print_r($result);

代码关键修改说明

  1. 新增$startIndex参数:这是避免重复的核心,它控制每次递归遍历的起始位置,确保我们不会重复选取之前已经处理过的元素。
  2. 调整终止条件:当$level减到0时,说明当前组合的元素数量已经满足要求,直接将其加入结果数组即可。
  3. 移除冗余去重逻辑:因为生成的每个组合都是唯一的元素集合,不需要再用sort()和in_array()做额外的去重操作,效率更高。

运行结果

执行后会生成你预期的所有无重复组合:

Array
(
    [0] => Array
        (
            [0] => PER_DAY
        )

    [1] => Array
        (
            [0] => PER_SIZE
        )

    [2] => Array
        (
            [0] => PER_TYPE
        )

    [3] => Array
        (
            [0] => PER_DAY
            [1] => PER_SIZE
        )

    [4] => Array
        (
            [0] => PER_DAY
            [1] => PER_TYPE
        )

    [5] => Array
        (
            [0] => PER_SIZE
            [1] => PER_TYPE
        )

    [6] => Array
        (
            [0] => PER_DAY
            [1] => PER_SIZE
            [2] => PER_TYPE
        )
)

内容的提问来源于stack exchange,提问作者Angga Ari Wijaya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:16:23