如何根据列表项的嵌套内容递归删除列表项

问题描述 投票:0回答:1

我正在尝试根据嵌套内容递归删除列表项(如果

checked = TRUE
则删除)。

我最近问了一个类似的问题这里。然而,我刚刚意识到给定的答案不能递归地工作。

这是我的示例数据:

library(jsTreeR)
library(jsonlite)

nodes <- list(
  list(
    text = "Branch 1",
    state = list(
      opened = TRUE,
      disabled = FALSE,
      selected = FALSE
    ),
    type = "parent",
    children = list(
      list(
        text = "Leaf A",
        state = list(
          opened = TRUE,
          disabled = FALSE,
          selected = FALSE,
          checked = FALSE
        ),
        type = "child"
      ),
      list(
        text = "Leaf B",
        state = list(
          opened = TRUE,
          disabled = FALSE,
          selected = FALSE,
          checked = FALSE
        ),
        type = "child"
      ),
      list(
        text = "Leaf C",
        state = list(
          opened = TRUE,
          disabled = FALSE,
          selected = FALSE,
          checked = TRUE
        ),
        type = "child"
      ),
      list(
        text = "Leaf D",
        state = list(
          opened = TRUE,
          disabled = FALSE,
          selected = FALSE,
          checked = FALSE
        ),
        type = "child",
        children = list(
          list(
            text = "Leaf D1",
            state = list(
              opened = TRUE,
              disabled = FALSE,
              selected = FALSE,
              checked = FALSE
            ),
            type = "child"
          ),
          list(
            text = "Leaf D2",
            state = list(
              opened = TRUE,
              disabled = FALSE,
              selected = FALSE,
              checked = TRUE
            ),
            type = "child"
          )
        )
      )
    )
  ),
  list(
    text = "Branch 2",
    type = "parent",
    state = list(
      opened = TRUE,
      disabled = FALSE,
      selected = FALSE,
      checked = FALSE
    )
  )
)


jstree(nodes, checkboxes = TRUE, checkWithText = FALSE)
# toJSON(nodes, pretty = TRUE)

我尝试使用base R和rrapply,但无法让它正常工作:

delete_unchecked <- function(x) {
  for (i in seq_along(x)) {
    value <- x[[i]]
    if (is.list(value)) {
      x[[i]] <- delete_unchecked(value)
    } else {
      if("state" %in% names(x) && isTRUE(x$state$checked)){x[[i]] <- NULL}
    }
  }
  x
}

library(rrapply)
result <- rrapply(nodes, condition = function(x){
  if("state" %in% names(x)){
    isTRUE(x$state$checked)
  } else {TRUE}
}, how = "prune")

这是我的预期输出:

expected_output <- list(
  list(
    text = "Branch 1",
    state = list(
      opened = TRUE,
      disabled = FALSE,
      selected = FALSE
    ),
    type = "parent",
    children = list(
      list(
        text = "Leaf A",
        state = list(
          opened = TRUE,
          disabled = FALSE,
          selected = FALSE,
          checked = FALSE
        ),
        type = "child"
      ),
      list(
        text = "Leaf B",
        state = list(
          opened = TRUE,
          disabled = FALSE,
          selected = FALSE,
          checked = FALSE
        ),
        type = "child"
      ),
      list(
        text = "Leaf D",
        state = list(
          opened = TRUE,
          disabled = FALSE,
          selected = FALSE,
          checked = FALSE
        ),
        type = "child",
        children = list(
          list(
            text = "Leaf D1",
            state = list(
              opened = TRUE,
              disabled = FALSE,
              selected = FALSE,
              checked = FALSE
            ),
            type = "child"
          )
        )
      )
    )
  ),
  list(
    text = "Branch 2",
    type = "parent",
    state = list(
      opened = TRUE,
      disabled = FALSE,
      selected = FALSE,
      checked = FALSE
    )
  )
)

PS:我更喜欢基本的 R 答案 - 但是,欢迎其他建议。

r recursion purrr jstreer
1个回答
0
投票

您可以使用一些递归来检查每个节点及其子节点

remove_checked <- function(x) {
  drop_null <- function(x) Filter(Negate(is.null), x)
  is_checked <- function(x) "state" %in% names(x) && "checked" %in% names(x$state) && x$state$checked
  drop <- function(x) {
    if (is_checked(x)) return(NULL)
    if ("children" %in% names(x)) {
      x$children <- drop_null(lapply(x$children, drop))
    }
    x
  }
  drop_null(lapply(x, drop))
}
result <- remove_checked(nodes)

我们用 NULL 替换已检查的内容,然后从列表中删除 NULL。

© www.soinside.com 2019 - 2024. All rights reserved.