提问人:ahnungslos 提问时间:11/17/2023 最后编辑:ahnungslos 更新时间:11/18/2023 访问量:40
如何根据列表项的嵌套内容递归删除列表项
How to recursively delete list items based on its nested content
问:
我正在尝试根据其嵌套内容递归删除列表项(如果删除)。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)
我尝试使用基础 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 基础答案 - 但是,对其他建议持开放态度。
答:
1赞
MrFlick
11/18/2023
#1
您可以使用一些递归来检查每个节点及其子节点
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,然后从列表中删除 NULL。
评论