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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 09:01:37