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); }
关键修改说明
- 修复递归分支:新增“包含当前ID”的递归分支,正确更新
current_combination和current_sum - 过滤无效组合:在匹配成功时,增加
!empty($current_combination)和count($current_combination) != count($ids)判断,排除全0和全1行 - 优化数据库操作:直接构建包含0和1的数值数组,一次完成插入,避免冗余的UPDATE操作
- 类型转换:将
$bultos_value转为int类型,确保求和计算的准确性
额外注意事项
- 确保
$table_name_temp_bultos表存在自增的id主键(如果需要后续操作),否则可忽略相关逻辑 - 若处理的ID数量较多,递归可能导致栈溢出,建议改用迭代方式实现组合查找
- 建议开启PDO异常模式,方便排查数据库错误:
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
内容的提问来源于stack exchange,提问作者Kendo
相关产品推荐
相关产品推荐

