基于嵌套内容递归筛选R列表节点(保留selected=TRUE项)
问题与解决方案
需求
给定嵌套列表数据,需递归删除所有selected = FALSE的节点,同时移除删除后无剩余子节点的父节点;等价于保留所有selected = TRUE的节点及其祖先节点,维持原列表结构(参考下方expected_output)。
原始代码与错误
编写的递归函数执行时抛出Error in x[[i]] : subscript out of bounds错误,原始代码如下:
# 输入数据 nodes <- list( list( text = "RootA", state = list(loaded = TRUE, opened = TRUE, selected = TRUE, disabled = FALSE), children = list( list( text = "ChildA1", state = list(loaded = TRUE, opened = TRUE, selected = TRUE, disabled = FALSE) ), list( text = "ChildA2", state = list(loaded = TRUE, opened = TRUE, selected = FALSE, disabled = FALSE) ) ) ), list( text = "RootB", state = list(loaded = TRUE, opened = TRUE, selected = FALSE, disabled = FALSE), children = list( list( text = "ChildB1", state = list(loaded = TRUE, opened = TRUE, selected = FALSE, disabled = FALSE) ), list( text = "ChildB2", state = list(loaded = TRUE, opened = TRUE, selected = FALSE, disabled = FALSE) ) ) ) ) # 报错的递归函数 delete_unselected_nodes <- function(x) { y <- list() for (i in seq_along(x)) { value <- x[[i]] if("state" %in% names(x)){ if(x[["state"]][["selected"]] == TRUE) { y <- c(y, x[[i]]) } } else { x[[i]] <- delete_unselected_nodes(value) } } } # 执行报错 delete_unselected_nodes(nodes) # 期望输出 expected_output <- list( list( text = "RootA", state = list(loaded = TRUE, opened = TRUE, selected = TRUE, disabled = FALSE), children = list( list( text = "ChildA1", state = list(loaded = TRUE, opened = TRUE, selected = TRUE, disabled = FALSE) ) ) ) )
错误原因分析
- 节点属性判断错误:原函数中
"state" %in% names(x)判断的是当前遍历的列表(而非单个节点)是否包含state属性,逻辑完全错误,应判断单个节点的属性。 - 递归逻辑混乱:未先递归处理节点的
children子列表,也未将处理后的节点正确添加到结果列表中。 - 无返回值:函数未返回处理后的结果列表,导致递归调用时传递空值,引发下标越界错误。
修复后的递归函数
delete_unselected_nodes <- function(x) { # 处理空列表边界情况 if (length(x) == 0) return(list()) result <- list() for (node in x) { # 先递归处理当前节点的子节点 if ("children" %in% names(node)) { node$children <- delete_unselected_nodes(node$children) } # 判断是否保留当前节点: # 1. 节点自身selected为TRUE,直接保留 # 2. 节点处理后的子列表不为空(说明有后代节点被保留),保留 keep_node <- FALSE if ("state" %in% names(node) && node$state$selected) { keep_node <- TRUE } if ("children" %in% names(node) && length(node$children) > 0) { keep_node <- TRUE } if (keep_node) { result <- c(result, list(node)) } } result }
验证结果
执行修复后的函数,输出与expected_output完全一致:
output <- delete_unselected_nodes(nodes) identical(output, expected_output) # [1] TRUE
内容的提问来源于stack exchange,提问作者ahnungslos
相关产品推荐
相关产品推荐

