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

基于嵌套内容递归筛选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)
      )
    )
  )
)

错误原因分析

  1. 节点属性判断错误:原函数中"state" %in% names(x)判断的是当前遍历的列表(而非单个节点)是否包含state属性,逻辑完全错误,应判断单个节点的属性。
  2. 递归逻辑混乱:未先递归处理节点的children子列表,也未将处理后的节点正确添加到结果列表中。
  3. 无返回值:函数未返回处理后的结果列表,导致递归调用时传递空值,引发下标越界错误。

修复后的递归函数

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 10:06:03