如何对父子DataFrame执行递归迭代查找并整合结果
解决递归查询本体数据库并合并结果的问题
我来帮你搞定这个递归查询的需求!你需要的是深度优先遍历每个返回的编号,处理完所有子节点后再回到父级继续,最后把所有查询结果(包括初始的df1)合并成一个DataFrame。下面是具体的实现步骤和代码:
第一步:模拟查询函数
首先我们需要模拟你的lookup函数(你可以直接替换成你实际的数据库查询函数),它接收一个编号,返回对应的DataFrame,没有结果就返回空:
# 模拟你的lookup查询函数,匹配你给出的示例数据 lookup <- function(id) { switch(id, "C123" = data.frame(Nums = c("Coo","Noo","Too"), Text = c("Tim","Slim","Shim"), stringsAsFactors = FALSE), "Coo" = data.frame(Nums = c("S144","S199","S743"), Text = c("Ellie","Bellie","Tellie"), stringsAsFactors = FALSE), "Noo" = data.frame(Nums = c("GHS","THE","PAA"), Text = c("Front","Bunt","Shunt"), stringsAsFactors = FALSE), # 其他编号返回空DataFrame data.frame(Nums = character(0), Text = character(0), stringsAsFactors = FALSE) ) }
第二步:编写递归遍历函数(迭代实现,避免栈溢出)
我们用**栈(Stack)**来实现深度优先遍历,这样就能保证处理完子节点的所有子查询后,再回到父级继续处理剩余的编号。同时加入了去重逻辑,避免重复查询同一个编号(防止循环或冗余工作):
# 定义递归查询主函数 recursive_lookup <- function(initial_ids) { # 存储所有查询到的DataFrame results_list <- list() # 记录已查询过的ID,避免重复操作 queried_ids <- character(0) # 初始化栈:放入初始需要查询的编号 stack <- initial_ids # 循环处理栈中的每个ID while(length(stack) > 0) { # 取出栈顶的ID(深度优先:先处理最新的子节点) current_id <- stack[length(stack)] stack <- stack[-length(stack)] # 如果该ID已查询过,直接跳过 if(current_id %in% queried_ids) next # 执行查询,获取当前ID的结果DataFrame current_df <- lookup(current_id) # 如果查询有结果,加入结果列表 if(nrow(current_df) > 0) { results_list[[length(results_list) + 1]] <- current_df } # 标记该ID已查询 queried_ids <- c(queried_ids, current_id) # 将当前结果中的所有编号加入栈,等待后续查询 # 注意顺序:保持深度优先,所以把新编号加到栈尾 stack <- c(stack, current_df$Nums) } # 别忘了把初始的df1也加入结果列表(你要求最终合并所有行) results_list[[length(results_list) + 1]] <- df1 # 合并所有DataFrame为最终结果 final_df <- do.call(rbind, results_list) # 重置行名,避免混乱 rownames(final_df) <- NULL return(final_df) }
第三步:初始化初始数据并测试
先初始化你给出的初始DataFrame df1,然后运行函数得到最终结果:
# 初始化初始查询的df1 Numsdf1 <- c("C123","C456","C789") Textdf1 <- c("Harry","Bobby","Terry") df1 <- data.frame(Nums = Numsdf1, Text = Textdf1, stringsAsFactors = FALSE) # 运行递归查询 final_result <- recursive_lookup(df1$Nums) # 查看最终结果 print(final_result)
关键说明
- 深度优先遍历:通过栈的“后进先出”特性,实现了先处理完某个节点的所有子节点,再回到父节点处理剩余节点的需求,完全符合你的要求。
- 去重逻辑:
queried_ids列表确保每个编号只被查询一次,既节省资源,也避免了可能的循环引用(比如A的子节点是B,B的子节点是A的情况)。 - 灵活替换:你只需要把模拟的
lookup函数替换成你实际的数据库查询函数即可,其他逻辑不需要改动。
内容的提问来源于stack exchange,提问作者Sebastian Zeki
相关产品推荐
相关产品推荐

