在列表的嵌套列表中查找空列表
Find empty lists in nested list of lists
给定一个任意嵌套的列表,我如何判断一个列表是否包含空列表?考虑以下示例:
mylist <- list(list("foo", "bar", "baz", list(list())))
我试过 rapply
,但它跳过了列表。虽然我可以使用 lapply
,但我需要事先知道嵌套级别。对于这个练习,我不需要知道列表在哪里(尽管那将是一个奖励),我只需要一种方法来检测是否有一个列表。
这样的函数怎么样
has_empty_list <- function(x) {
if(is.list(x)) {
if (length(x)==0) {
return(TRUE)
} else {
return(any(vapply(x, has_empty_list, logical(1))))
}
} else {
return(FALSE)
}
}
基本上我们创建了一个递归函数来查找长度为 0 的列表。
has_empty_list( list(list("foo", "bar", "baz", list(list()))) )
# TRUE
has_empty_list( list(list("foo", "bar", "baz", list(list(4)))) )
# FALSE
这里修改一下找到空列表的索引
find_empty_list <- function(x, index=c()) {
if(is.list(x)) {
#list
if (length(x)==0) {
if (length(index)==0) {
return(0)
} else {
return(index)
}
} else {
m <- Map(find_empty_list, x, lapply(seq_along(x), function(i) append(index,i)))
# return the most deeply nested
return( m[[which.max(lengths(m))]] )
}
} else {
return(numeric())
}
}
这应该 return 一个索引向量,您可以使用它来查找空列表。例如
( i <- find_empty_list(mylist) )
# [1] 1 4 1
mylist[[i]]
# list()
如果第一个参数本身是一个空列表,它将return 0
find_empty_list(list())
# 0
如果没有空列表,它应该return一个空向量
find_empty_list(list(1:3, list("c", a~b)))
# numeric()
使用嵌套列表的另一个方便的选项是使用 data.tree
包:
library(data.tree)
nodes <- as.Node(mylist)
any(node$Get(function(node) length(as.list(node))) == 0)
# [1] TRUE
另一种方法是在 rrapply
包中使用 rrapply
(base-rrapply
的扩展):
library(rrapply)
## check if any empty list exists
any(
rrapply(mylist,
classes = "list",
condition = function(x) length(x) < 1,
f = function(x) TRUE,
deflt = FALSE,
how = "unlist"
)
)
#> [1] TRUE
将上述调用更新为 return 任何空列表的索引向量很简单:
## return flat list with position vectors of empty list
rrapply(mylist,
classes = "list",
condition = function(x) length(x) < 1,
f = function(x, .xpos) .xpos,
how = "flatten"
)
#> [[1]]
#> [1] 1 4 1
在这里,我们使用 .xpos
参数计算当前列表元素的位置。
请注意,这会自动 return 所有空列表位置,而不是只有一个:
mylist2 <- list(list("foo", list(), "baz", list(list())))
rrapply(mylist2,
classes = "list",
condition = function(x) length(x) < 1,
f = function(x, .xpos) .xpos,
how = "flatten"
)
#> [[1]]
#> [1] 1 2
#>
#> [[2]]
#> [1] 1 4 1
## using MrFlick's find_empty_list function
find_empty_list(mylist2)
#> [1] 1 4 1
给定一个任意嵌套的列表,我如何判断一个列表是否包含空列表?考虑以下示例:
mylist <- list(list("foo", "bar", "baz", list(list())))
我试过 rapply
,但它跳过了列表。虽然我可以使用 lapply
,但我需要事先知道嵌套级别。对于这个练习,我不需要知道列表在哪里(尽管那将是一个奖励),我只需要一种方法来检测是否有一个列表。
这样的函数怎么样
has_empty_list <- function(x) {
if(is.list(x)) {
if (length(x)==0) {
return(TRUE)
} else {
return(any(vapply(x, has_empty_list, logical(1))))
}
} else {
return(FALSE)
}
}
基本上我们创建了一个递归函数来查找长度为 0 的列表。
has_empty_list( list(list("foo", "bar", "baz", list(list()))) )
# TRUE
has_empty_list( list(list("foo", "bar", "baz", list(list(4)))) )
# FALSE
这里修改一下找到空列表的索引
find_empty_list <- function(x, index=c()) {
if(is.list(x)) {
#list
if (length(x)==0) {
if (length(index)==0) {
return(0)
} else {
return(index)
}
} else {
m <- Map(find_empty_list, x, lapply(seq_along(x), function(i) append(index,i)))
# return the most deeply nested
return( m[[which.max(lengths(m))]] )
}
} else {
return(numeric())
}
}
这应该 return 一个索引向量,您可以使用它来查找空列表。例如
( i <- find_empty_list(mylist) )
# [1] 1 4 1
mylist[[i]]
# list()
如果第一个参数本身是一个空列表,它将return 0
find_empty_list(list())
# 0
如果没有空列表,它应该return一个空向量
find_empty_list(list(1:3, list("c", a~b)))
# numeric()
使用嵌套列表的另一个方便的选项是使用 data.tree
包:
library(data.tree)
nodes <- as.Node(mylist)
any(node$Get(function(node) length(as.list(node))) == 0)
# [1] TRUE
另一种方法是在 rrapply
包中使用 rrapply
(base-rrapply
的扩展):
library(rrapply)
## check if any empty list exists
any(
rrapply(mylist,
classes = "list",
condition = function(x) length(x) < 1,
f = function(x) TRUE,
deflt = FALSE,
how = "unlist"
)
)
#> [1] TRUE
将上述调用更新为 return 任何空列表的索引向量很简单:
## return flat list with position vectors of empty list
rrapply(mylist,
classes = "list",
condition = function(x) length(x) < 1,
f = function(x, .xpos) .xpos,
how = "flatten"
)
#> [[1]]
#> [1] 1 4 1
在这里,我们使用 .xpos
参数计算当前列表元素的位置。
请注意,这会自动 return 所有空列表位置,而不是只有一个:
mylist2 <- list(list("foo", list(), "baz", list(list())))
rrapply(mylist2,
classes = "list",
condition = function(x) length(x) < 1,
f = function(x, .xpos) .xpos,
how = "flatten"
)
#> [[1]]
#> [1] 1 2
#>
#> [[2]]
#> [1] 1 4 1
## using MrFlick's find_empty_list function
find_empty_list(mylist2)
#> [1] 1 4 1