2013-05-21 57 views
2

R是否有一种优雅的方式递归地将任意深度列表(包含列表和向量)转换为路径向量?例如,转换这样的:递归对象列表

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

要一个对象作为这样的:unlist

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

回答

1

的名称不约你想要什么:

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

把手递归的多个级别,以及:

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

从那里可以很容易地添加你想要的(具有终值是最后一个路径elemtn)上的最后一点:

> 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"  
4

只要不关你的列表中的元素都有名字,其中包括点(与在您的列表麻烦NULL -valued etc元)外,这应该工作:

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"  
+0

谢谢。我已经把'etc'改成了一个向量,而不是一个名字。现在它运作良好。 – Jeroen

3

对于一个更通用的方法,包括用点和空元素posdibly名称,使用此:

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" 
+0

很酷。大量使用'Recall'来递归调用一个匿名函数。 – Jeroen

+0

超级。谢谢你。我相信我会将它用作未来其他树形漫步功能的模板。 –

+0

:-) @ JoshO'Brien,关键的想法是有一个参数来跟踪你的深度水平(默认为零或空或类似)。 –