Recursive Listing Object

Is there an elegant way in R to recursively turn an arbitrary deep list (containing lists and vectors) into a path vector? For example, convert this:

list(
  home = list(
    jerry = c("R", "bla"),
    mary = "xx"
  ),
  tmp = c("foo", "bar"),
  c("etc")
)

For an object as follows:

c(
  "/home/jerry/R",
  "/home/jerry/bla",
  "/home/mary/xx",
  "/tmp/foo",
  "/tmp/bar",
  "/etc"
 )
+2
source share
3 answers

The names in unlistdo roughly what you want:

> test <- list(
+     home = list(
+         jerry = c("R", "bla"),
+         mary = "xx"
+     ),
+     tmp = c("foo", "bar"),
+     etc = c()
+ )
> unlist(test)
home.jerry1 home.jerry2   home.mary        tmp1        tmp2 
        "R"       "bla"        "xx"       "foo"       "bar" 

Manages several levels of recursion:

> test <- list(
+     home = list(
+         jerry = list(a="R", b="bla"),
+         mary = list(c="xx")
+     ),
+     tmp = list(d="foo", e="bar"),
+     etc = list(nothing=NULL)
+ )
> unlist(test)
home.jerry.a home.jerry.b  home.mary.c        tmp.d        tmp.e 
         "R"        "bla"         "xx"        "foo"        "bar" 

From there it’s easy to add the last bit you want (with the final value there will be the last elemtn path):

> unl <- unlist(test)
> res <- names(unl)
> res <- paste(res,unl,sep=".")
> res
[1] "home.jerry.a.R"   "home.jerry.b.bla" "home.mary.c.xx"   "tmp.d.foo"        "tmp.e.bar"       
+1
source

As long as none of your list items has names containing NULLperiods (and with the exception of this inconvenient -valueded element etcin your list), this should work:

ll <- rapply(l, function(X) sapply(X,list), how="replace") #for tip element names
nms <- names(unlist(ll))
gsub(".", "/", nms, fixed=TRUE)
# [1] "home/jerry/R"   "home/jerry/bla" "home/mary/xx"   "tmp/foo"       
# [5] "tmp/bar"    
+4

, , :

f <- function(test, parent=character(0))
{
    if( is.null(test) ) return(parent)

    if( is.list(test) )
    {
        result <- character(0)

        for( i in seq_along(test) )
        {
            result <- c(result, Recall(test[[i]], parent=paste0(parent,"/",names(test)[i])))
        }
    }
    else
    {
        result <- paste0(parent,"/",as.character(test))
    }

    result
}

f(test)

#[1] "/home/jerry/R"   "/home/jerry/bla" "/home/mary/xx"   "/tmp/foo"        "/tmp/bar"        "/etc" 
+3

All Articles