I'm trying to recursively delete list items based on their nested content (delete if checked = TRUE
).
I recently asked a similar question here. However, I just realized that the given answer doesn't work recursively.
Here is my example data:
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)
I tried using base R and {rrapply}, but can't get it to work properly:
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")
This is my expected output:
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: I'd prefer base R answers - however, open to other suggestions.
You can use some recursion to check each node and it's children
We swap out the checked ones with NULL and then remove NULL from the list.