递归地从列表列表中提取元素

时间:2015-01-26 01:05:45

标签: r list

我有以下类型的嵌套列表:

我有什么

mylist <- list(
    "A",
    list(
        "B1",
        list(
            "C_B1",
            "w"
        ),
        "B2",
        list(
            "C_B2",
            "x"
        ),
        "B3",
        list(
            "C_B3_1",
            list(
                "D_B3_1",
                "y"
            ),
            "C_B3_2",
            list(
                 "D_B3_2",
                 "z"
            )
        )
    )
)

这里列表的名称实际上存储为一个模式,似乎是一个名称后跟一个列表或单个元素。此模式可以扩展任意次,并且在每个列表中可以重复模式。

此数据来自 NLP 包中的树结构。以下是此结构的示例:https://dl.dropboxusercontent.com/u/61803503/Errors/sample.R

所需输出

list(
    A = list(
        B1 = list(
            C_B1 = "w"
        ),
        B2 = list(
            C_B2 = "x"
        ),
        B3 = list(
            C_B3_1 = list(
                D_B3_1 = "y"
            ),
            C_B3_2 = list(
                 D_B3_2 = "z"
            )
        )
    )
)

## $A
## $A$B1
## $A$B1$C_B1
## [1] "w"
## 
## 
## $A$B2
## $A$B2$C_B2
## [1] "x"
## 
## 
## $A$B3
## $A$B3$C_B3_1
## $A$B3$C_B3_1$D_B3_1
## [1] "y"
## 
## 
## $A$B3$C_B3_2
## $A$B3$C_B3_2$D_B3_2
## [1] "z"

注意 无法保证嵌套程度,只是有一个列表列表,每个列表的第一个元素是值的名称(列表中的第二个元素)。

2 个答案:

答案 0 :(得分:1)

我依赖于问题陈述“这里列表的名称实际上存储为每个列表中的第一个元素。”并使用遵循此规则的更正示例。

mylist <- 
list( "A",
    list("B1",
        list("C_B1",
            "w"),
        list("B2",
            list( "C_B2",
                "x")),
        list("B3",
            list( "C_B3_1",
                list( "D_B3_1",
                    "y"),
                list("C_B3_2",
                    list("D_B3_2",
                        "z")
                )
            )
        )
    )
)

递归遍历列表列表的一种方法是编写递归函数,如下所示:

firstEltAsName  <-  function(x){
    # if x is not a list, return x
    if(!inherits(x,'list'))
        return(x)
    # recurse on everythin but the first element
    out  <-  lapply(x[-1],firstEltAsName)
    # take the names from the first element of the remaining elements.
    names(out)  <-  sapply(x[-1],`[`,1)
    # use the first element as the name 
    return(out)
}
firstEltAsName( mylist)

如果您的示例实际上是正确的,那么您需要:

OddEltsAsNames  <-  function(x){
    stopifnot(length(x)%%2 == 0)

    # recurse on the even elements
    out  <-  lapply(x[which(seq_along(x)%%2 == 0)],firstEltAsName)

    # take the names from the even elements 
    names(out)  <-  unlist( x[which(seq_along(x)%%2 == 1)] )

    return(out)
}
OddEltsAsNames( mylist)

答案 1 :(得分:1)

有点难看,但有效:

library(magrittr)

stackUp = function(lst)
{
    cond = lst %>% sapply(is.list) %>% any

    if(!cond) return(setNames(list(lst[[2]]), lst[[1]]))

    index = seq(1, length(lst), 2)

    index %>%
        lapply(function(u) stackUp(lst[[u+1]]))  %>%
        setNames(sapply(index, function(u) lst[[u]]))
}

> stackUp(mylist)
#$A
#$A$B1
#$A$B1$C_B1
#[1] "w"


#$A$B2
#$A$B2$C_B2
#[1] "x"


#$A$B3
#$A$B3$C_B3_1
#$A$B3$C_B3_1$D_B3_1
#[1] "y"


#$A$B3$C_B3_2
#$A$B3$C_B3_2$D_B3_2
#[1] "z"