我正在尝试根据嵌套内容递归删除列表项(如果
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 答案 - 但是,欢迎其他建议。
您可以使用一些递归来检查每个节点及其子节点
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。