2013-03-13 113 views
3

是否有一个“内置”/有效和健壮的方式来检查列表对象是否嵌套?检查一个列表是否嵌套

为了澄清我的术语的理解嵌套

平或不嵌套列表

x.1 <- list(
    a=TRUE, 
    b=1:5 
) 

嵌套列表

x.2 <- list(
    a=list(a.1=list(a.1.1=TRUE)), 
    b=list(b.1=1:5) 
) 

我的第一个想法是使用的组合,capture.output和正则表达式。但随着相关的一切正则表达式:非常强大,在坚固性方面相当危险;-)所以,我想知道是否有更好的东西在那里:

isNested <- function(x) { 
    if (class(x) != "list") { 
     stop("Expecting 'x' to be a list") 
    } 
    out <- FALSE 
    strout <- capture.output(str(x)) 
    idx <- grep("\\$.*List", strout) 
    if (length(idx)) { 
     out <- TRUE 
    } 
    return(out) 
} 

> isNested(x=x.1) 
[1] FALSE 
> isNested(x=x.2) 
[1] TRUE 

第二条本办法礼貌罗马和阿伦的:

isNested2 <- function(x) { 
    if (class(x) != "list") { 
     stop("Expecting 'x' to be a list") 
    } 
    out <- any(sapply(x, is.list)) 
    return(out) 
} 

> isNested2(x=x.1) 
[1] FALSE 
> isNested2(x=x.2) 
[1] TRUE 
+1

如果您是第一个订单清单,如果班级是清单,该怎么办?如果是的话,它是嵌套的,否则不是。 (任何(sapply(x.2,function(x)class(x)==“list”))''的行。 'any(sapply(x.1,function(x)class(x)==“list”))'返回FALSE。 – 2013-03-13 10:06:33

+1

'any(sapply(my_list,class)==“list”)' – Arun 2013-03-13 10:07:54

+0

好吧,那会更容易;-)谢谢你们!作为第二种方法嵌入您的方法。欢呼 – Rappster 2013-03-13 10:10:57

回答

6

可以使用is.list功能:

any(sapply(x.1, is.list)) 
[1] FALSE 

any(sapply(x.2, is.list)) 
[1] TRUE 

作为一个功能isNested

isNested <- function(l) { 
    stopifnot(is.list(l)) 
    for (i in l) { 
    if (is.list(i)) return(TRUE) 
    } 
    return(FALSE) 
} 

而是测试所有列表中的元素,功能,因为它检测到一个嵌套列表就停止。

2

试试这个:

isNested <- function(x) { 
    if (is.list(x)) 
     stop("Expecting 'x' to be a list") 

    any(unlist(lapply(x,is.list))) 
    } 
+0

谢谢你的回答并把它放到“我的函数上下文”中!把它交给斯文,因为它只是更简洁一点而已。干杯 – Rappster 2013-03-13 10:25:44

2

这里的另一种方式为它的乐趣:

length(unlist(l, FALSE)) != length(unlist(l)) 

或者在一个变化:

!identical(unlist(l, FALSE), unlist(l)) 

利用的recursive参数unlist()。如果您想要,还可以进行错误检查:

isNested <- function(l) { 
    if (!is.list(l)) stop("Not a list.") 
    !identical(unlist(l, FALSE), unlist(l)) 
}