R语言Tidyverse递归函数生成BOM物料路径异常排查
BOM树形结构物料完整路径递归生成修复方案
问题背景
在BOM树形结构场景中,需要用递归函数生成物料的完整路径,但现有代码在新数据集下失效:新数据集中成品(根节点)的matID为NA,导致共享子组件(如matID=5、6)的物料路径错误,预期路径应为[5,3,2,1]和[6,3,2,1],实际生成错误路径。
原数据集:
BOM <- tibble( bomID = 1:24, finiGoodID = c(rep(1, 12), rep(2, 12)), matID = c(NA, 2, 3, 4, 5, 6, 7, 8, 9, 10, 5, 6, NA , 12, 13, 14, 15, 16, 17, 18, 19, 20, 5, 6), parentMatID = c(NA, 1, 2, 2, 4, 4, 4, 4, 4, 1, 3, 3, NA, 11, 12, 12, 14, 14, 14, 14, 14, 11, 13, 13))
原递归函数:
bomPath <- function(mat, p, fg) { row <- subset(BOM, matID == mat & parentMatID == p & finiGoodID == fg) if (nrow(row) == 0) { return(mat) } if (is.na(p)) { return(mat) } else { # Recursively build the path rownew <- subset(BOM, matID == p & finiGoodID == fg) parent_path <- sapply(rownew$parentMatID, \(x) bomPath(p, x, fg)) return(c(mat, parent_path)) } }
原调用方式:
for (i in 1:nrow(BOM)) { path = bomPath(BOM$matID[i], BOM$finiGoodID[i]) print(path) }
原代码问题分析
- 调用参数错误:原调用将
finiGoodID作为第二个参数传入函数,但函数定义中第二个参数应为parentMatID,导致递归起始逻辑完全错误 - 根节点处理缺失:未将成品ID(
finiGoodID)纳入路径,当parentMatID指向成品ID(如1、11)时,无法完成根节点的路径拼接 - 递归逻辑冗余:
sapply处理父路径时可能生成重复内容,且未针对父节点为成品的场景做特殊处理
修正后的代码
递归路径生成函数
bomPath <- function(mat, parent_mat, fg) { # 跳过根节点(matID为NA的成品行) if (is.na(mat)) { return(NULL) } # 父节点是成品ID时,直接返回当前物料+成品ID的路径 if (parent_mat == fg) { return(c(mat, fg)) } # 查找当前父节点的BOM记录 parent_row <- subset(BOM, matID == parent_mat & finiGoodID == fg) # 异常处理:父节点不存在时返回当前物料 if (nrow(parent_row) == 0) { return(mat) } # 递归获取父节点的完整路径 parent_path <- bomPath(parent_mat, parent_row$parentMatID, fg) # 拼接当前物料与父节点路径 return(c(mat, parent_path)) }
正确调用方式
# 生成所有物料的路径并添加到BOM数据集 BOM$path <- lapply(1:nrow(BOM), function(i) { bomPath(BOM$matID[i], BOM$parentMatID[i], BOM$finiGoodID[i]) }) # 查看结果(重点验证共享子组件路径) print(BOM[BOM$matID %in% c(5,6), c("bomID", "matID", "parentMatID", "finiGoodID", "path")])
验证结果
修正后,bomID=11(matID=5,parentMatID=3,finiGoodID=1)的路径为[5,3,2,1],bomID=12(matID=6,parentMatID=3,finiGoodID=1)的路径为[6,3,2,1],完全符合预期;其他物料的路径也能正确追溯到对应成品根节点。
内容的提问来源于stack exchange,提问作者LHA
相关产品推荐
相关产品推荐

