6

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

为了澄清我对嵌套一词的理解:

扁平或非嵌套列表

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

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

第二种方法由 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
4

4 回答 4

10

您可以使用以下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)
}

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

于 2013-03-13T10:11:23.133 回答
3

试试这个 :

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

    any(unlist( lapply(x,is.list) ))
   }
于 2013-03-13T10:11:52.703 回答
3

这是另一种有趣的方式:

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))  
}
于 2013-03-13T12:18:16.720 回答
0

如果列表的内容是 S3 对象又具有嵌套列表怎么办?我希望这些被视为列表,因此这些对象的列表是“不嵌套的”(它只是一个对象列表而不是列表列表)。使用class()而不是is.list()检查是否按字面意思列出而不是使用嵌入列表的其他内容。

is.nested <- function(x) {
  stopifnot(is.list(x))
  any(sapply(x, function(x) any(class(x) == "list")))
}
于 2021-10-12T05:17:34.890 回答