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

PHP组合查找函数异常:无法标记有效组合列求助

组合求和与数据库插入问题

我编写了find_combinations函数,需求为:从$table_name_temp表的BULTOS(INT类型)列中,找出ID组合使其值之和等于指定变量$tar_bultos;找到符合条件的组合后,在$table_name_temp_bultos表(以$table_name_temp的ID为列名)中插入一行,将组合内ID对应列设为1,其余为0,且需找出所有符合条件的组合。但当前函数生成的行全为0,无法标记有效组合,且不应出现全0或全1的行。

原函数代码:

function find_combinations($ids, $tar_bultos, $pdo, $table_name_temp, $table_name_temp_bultos, $current_combination = [], $current_sum = 0)
{
    if ($current_sum == $tar_bultos) {
        // Crear una fila en la tabla $table_name_temp_bultos con 0 en todas las columnas
        $pdo->exec("INSERT INTO {$table_name_temp_bultos} (" . implode(',', $ids) . ") VALUES (" . implode(',', array_fill(0, count($ids), '0')) . ")");
        
        // Obtener el ID de la fila recién creada
        $row_id = $pdo->lastInsertId();

        // Actualizar la fila recién creada con los valores 1 en las columnas correspondientes
        foreach ($current_combination as $comb_id) {
            if (in_array($comb_id, $ids)) {
                $pdo->exec("UPDATE {$table_name_temp_bultos} SET {$comb_id} = 1 WHERE id = {$row_id}");
            }
        }
        return;
    }

    if (!$ids || $current_sum > $tar_bultos) {
        return;
    }

    $id = array_shift($ids);
    $bultos = $pdo->prepare("SELECT BULTOS FROM {$table_name_temp} WHERE ID = :id");
    $bultos->bindParam(':id', $id);
    $bultos->execute();
    $bultos_value = $bultos->fetchColumn();

    // Prueba sin incluir el ID actual en la combinación
    find_combinations($ids, $tar_bultos, $pdo, $table_name_temp, $table_name_temp_bultos, $current_combination, $current_sum);

 
    find_combinations($ids, $tar_bultos, $pdo, $table_name_temp, $table_name_temp_bultos, $current_combination, $current_sum);
}

问题根源

  • 递归逻辑完全错误:最后两次递归调用参数完全一致,没有处理“包含当前ID”的分支——既没有把当前ID加入current_combination,也没有把对应BULTOS值加到current_sum,导致永远找不到符合条件的组合,甚至会插入无意义的全0行
  • 未过滤无效组合:没有判断current_combination是否为空(对应全0行)或是否包含所有ID(对应全1行),不符合需求
  • 数据库操作冗余低效:先插入全0行再逐个更新,不仅效率低,还可能因事务问题导致数据不一致

修复后的代码

function find_combinations($ids, $tar_bultos, $pdo, $table_name_temp, $table_name_temp_bultos, $current_combination = [], $current_sum = 0)
{
    // 找到符合条件的组合,且排除全空或全选的情况
    if ($current_sum == $tar_bultos && !empty($current_combination) && count($current_combination) != count($ids)) {
        // 直接构建插入的数值数组,避免先插全0再更新
        $values = [];
        foreach ($ids as $col_id) {
            $values[] = in_array($col_id, $current_combination) ? '1' : '0';
        }
        // 执行插入操作
        $sql = "INSERT INTO {$table_name_temp_bultos} (" . implode(',', $ids) . ") VALUES (" . implode(',', $values) . ")";
        $pdo->exec($sql);
        return;
    }

    // 终止条件:无剩余ID或当前和超过目标值
    if (!$ids || $current_sum > $tar_bultos) {
        return;
    }

    $id = array_shift($ids);
    $bultos_stmt = $pdo->prepare("SELECT BULTOS FROM {$table_name_temp} WHERE ID = :id");
    $bultos_stmt->bindParam(':id', $id);
    $bultos_stmt->execute();
    $bultos_value = (int)$bultos_stmt->fetchColumn();

    // 分支1:不包含当前ID的情况
    find_combinations($ids, $tar_bultos, $pdo, $table_name_temp, $table_name_temp_bultos, $current_combination, $current_sum);

    // 分支2:包含当前ID的情况(更新组合和当前和)
    $new_combination = $current_combination;
    $new_combination[] = $id;
    $new_sum = $current_sum + $bultos_value;
    find_combinations($ids, $tar_bultos, $pdo, $table_name_temp, $table_name_temp_bultos, $new_combination, $new_sum);
}

关键修改说明

  1. 修复递归分支:新增“包含当前ID”的递归分支,正确更新current_combination和current_sum
  2. 过滤无效组合:在匹配成功时,增加!empty($current_combination)和count($current_combination) != count($ids)判断,排除全0和全1行
  3. 优化数据库操作:直接构建包含0和1的数值数组,一次完成插入,避免冗余的UPDATE操作
  4. 类型转换:将$bultos_value转为int类型,确保求和计算的准确性

额外注意事项

  • 确保$table_name_temp_bultos表存在自增的id主键(如果需要后续操作),否则可忽略相关逻辑
  • 若处理的ID数量较多,递归可能导致栈溢出,建议改用迭代方式实现组合查找
  • 建议开启PDO异常模式,方便排查数据库错误:
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    

内容的提问来源于stack exchange,提问作者Kendo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 01:42:48