根据手册,Filter适用于矢量,它也适用于列表,例如:
z <- list(a=1, b=2, c=3)
Filter(function(i){
z[[i]] > 1
}, z)
$b
[1] 2
$c
[1] 3
Run Code Online (Sandbox Code Playgroud)
但是,它不适用于列表列表,例如:
z <- list(z1=list(a=1,b=2,c=3), z2=list(a=1,b=1,c=1), z3=list())
Filter(function(i){
if(length(z[[i]])>0){
if(z[[i]]$b > 1)
TRUE
else
FALSE
}
else
FALSE
}, z)
Error in z[[i]] : invalid subscript type 'list'
Run Code Online (Sandbox Code Playgroud)
在不使用嵌套循环的情况下过滤列表列表的最佳方法是什么?它也可以是列表清单......
(我尝试使用嵌套lapply,但无法使其工作.)
编辑:在第二个例子中,这是我想要获得的:
list(z1=list(a=1,b=2,c=3))
Run Code Online (Sandbox Code Playgroud)
也就是说,没有z $ z2,因为z $ z2 $ b <1,没有z $ z3,因为它是空的.
我认为你应该使用:
Filter(function(x){length(x)>0 && x[["b"]] > 1},z)
Run Code Online (Sandbox Code Playgroud)
谓词(您用来过滤 z 的函数)适用于 z 的元素,而不是它们的索引。
这里没有对美丽的要求,也没有进行深度搜索:
z2 <- lapply(z, function(x){ if( "b" %in% names(x) && x[["b"]] >1 ) x else {} } )
z2[unlist(lapply(z2, is.null))] <- NULL
> z2
$z1
$z1$a
[1] 1
$z1$b
[1] 2
$z1$c
[1] 3
Run Code Online (Sandbox Code Playgroud)
编辑:此代码将遍历列表并组装“b”> 1 的节点。它需要一些工作来正确标记节点。首先是一个具有更深嵌套的列表:
z <- list(z1=list(a=1,b=2,c=3), z2=list(a=1,b=1,c=1), z3=list(),
z4 = list(z5=list(a=5,b=6,c=7), z6=list(a=7,b=8,c=9)))
checkbGT1 <- function(ll){ root <- list()
for(i in seq_along(ll) ) {if ("b" %in% names(ll[[i]]) && ll[[i]]$b >1) {
root <- c(root, ll[[i]])
}else{
if( length(ll[[i]]) && is.list(ll[[i]]) )
{ root <- c(root, list(checkbGT1( ll[[i]] ))) }
}
}
return(root) }
Run Code Online (Sandbox Code Playgroud)