检查列表是否嵌套

7

有没有一种“内置的”/高效且稳健的方法来检查列表对象是否嵌套?

为了澄清我对术语“嵌套”的理解:

平面或非嵌套列表

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)
)

我的第一个想法是使用strcapture.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

第二种方法由Roman和Arun提供:

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
如果您检查了第一个订单列表,是否为列表类?如果是,则它是嵌套的,否则不是。类似于any(sapply(x.2, function(x) class(x) == "list"))any(sapply(x.1, function(x) class(x) == "list"))返回FALSE。 - Roman Luštrik
2
any(sapply(my_list, class) == "list") - Arun
好的,那样做会更容易一些;-) 谢谢大家!我将你们的方法作为第二种方法嵌入其中。干杯! - Rappster
2
要获得额外的分数(列表嵌套有多深),请参见@Spacedman在此处的答案:https://dev59.com/9WYr5IYBdhLWcg3wvslA#13433689 - A5C1D2H2I1M1N2O1R2T1
@Rappster,any(.)已经提供了TRUE/FALSE。你不必将其包装在`if语句(或分配为FALSE)中。 - Arun
4个回答

13
你可以使用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)
}

函数不是测试所有列表元素,而是在检测到嵌套列表时立即停止。


4
尝试这个:

试一试:

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

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

谢谢你的回答并将其放入“我的函数上下文”中!虽然它更加简洁,但我还是把它给了Sven。干杯! - Rappster

3

以下是另一种有趣的方法:

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

或者是以下的一个变种:
!identical(unlist(l, FALSE), unlist(l))

运用unlist()函数的recursive参数。如果您想进行错误检查,也可以这样做:
isNested <- function(l) {
  if (!is.list(l)) stop("Not a list.")
  !identical(unlist(l, FALSE), unlist(l))  
}

0
如果列表的内容是具有嵌套列表的S3对象,那该怎么办?我希望这些对象被视为列表,因此这些对象的列表“不是嵌套的”(它只是一个对象列表而不是列表的列表)。使用class()而不是is.list()来检查是否确实是列表,而不是其他带有嵌入式列表的东西。
is.nested <- function(x) {
  stopifnot(is.list(x))
  any(sapply(x, function(x) any(class(x) == "list")))
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接