提问人:ahnungslos 提问时间:10/16/2023 最后编辑:ahnungslos 更新时间:10/17/2023 访问量:78
根据列表项的嵌套内容删除列表项
Delete list items based on its nested content
问:
这基本上是我之前问题的衍生问题。
考虑到以下示例数据,我想递归删除包含该项目的所有(以及没有更多子项的父项),反之亦然,在保持列表结构的同时复制所有包含该项目的内容(请参阅列表)。children
selected = FALSE
children
selected = TRUE
expected_output
到目前为止,我的尝试失败了:
# data --------------------------------------------------------------------
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)
)
)
)
)
# Error in x[[i]] : subscript out of bounds -------------------------------
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 ---------------------------------------------------------
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)
)
)
)
)
答:
3赞
dufei
10/17/2023
#1
我会使用 purrr 中的功能来处理列表并定义一些(谓词)函数以保持其整洁:
library(tidyverse)
library(lobstr)
# define sample data ------------------------------------------------------
# ...
# define functions --------------------------------------------------------
# filter list of children to keep only where selected == TRUE
delete_unselected_children <- function(children_list) {
keep(
children_list,
.p = \(x) x$state$selected)
}
# replace list element "children" of root with filtered list of children
delete_from_root <- function(root) {
modify_in(
root,
.where = list("children"),
.f = delete_unselected_children
)
}
# define predicate function to drop roots without children
has_no_children <- function(root) {
is_empty(root$children)
}
# apply -------------------------------------------------------------------
result <- nodes |>
map(delete_from_root) |>
discard(has_no_children)
lobstr::tree(result)
#> <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
创建于 2023-10-16 with reprex v2.0.2
评论