所有列表元素的索引路径

时间:2015-02-05 14:31:20

标签: r

如何获取所有列表元素的索引路径?

tree <- list(1:6,b=list(a=20:23,b=28),c=c("a","b"))

如何从现有列表树中获取所有叶子的寻址信息? 以向量列表的形式返回值,如下所示。

ret <- list(leaf1=c(1,1), .... ,leaf7=c(2,1,1), .... ,leaf13=c(3,2))
# tree[[c(2,1,1)]] should return 20 then.
# so the leaf7 value is indexing vector for tree$b$a[1] in another notation.
# so the tree$b$a[1] is same as tree[[ret$leaf7]]
# and so the object ret is then sort of a map of list "tree"

2 个答案:

答案 0 :(得分:3)

您的基本深度优先搜索。 Map / unlist组合用于保持结果列表平坦,因此else子句的叶级结果必须包含在列表中。 idx将当前索引保存到结构中,acc是叶子的累积索引。

index.leaves <- function(root) {
  walk <- function(node,idx,acc) {
    if(length(node)>1) {
      r<-Map(function(child,i) walk(child,c(idx,i),acc),node,seq_along(node))
      unlist(r,recursive=FALSE)
    }
    else {
      list(c(acc,idx))
    }
  }
  walk(root,NULL,c())
}

使用样本数据

str(index.leaves(tree))
List of 13
 $     : num [1:2] 1 1
 $     : num [1:2] 1 2
 $     : num [1:2] 1 3
 $     : num [1:2] 1 4
 $     : num [1:2] 1 5
 $     : num [1:2] 1 6
 $ b.a1: num [1:3] 2 1 1
 $ b.a2: num [1:3] 2 1 2
 $ b.a3: num [1:3] 2 1 3
 $ b.a4: num [1:3] 2 1 4
 $ b.b : num [1:2] 2 2
 $ c.a : num [1:2] 3 1
 $ c.b : num [1:2] 3 2

答案 1 :(得分:2)

一些递归方法,它们使用不同的方法来展平结果列表:

方法1 。深度优先搜索;一旦我们到达底部,将结果保存到上级变量L

nametree <- function(X) {
  L <- NULL

  rec <- function(X, prefix = NULL) {
    if( length(X) == 1 ) {L <<- c(L,list(prefix)); return()}    
    sapply(seq_along(X), function(i) rec(X[[i]], c(prefix,i)))
  }

  rec(X)
  L
}

方法2 。深度优先搜索;带索引的向量通过return保存。在这种情况下,结果是嵌套列表,因此应该展平,这是通过rapply/unlist/split组合实现的。

nametree2 <- function(X) {

  rec <- function(X, prefix = NULL) {
    if( length(X) == 1 ) return(prefix)    
    lapply(seq_along(X), function(i) rec(X[[i]], c(prefix,i)))
  }

  z <- rec(X)

  # Convert nested list into a simple list  
  z2 <- rapply(z,length)
  split(unlist(z),rep(seq_along(z2),z2))
}

z <- nametree(tree)
z2 <- nametree2(tree)

两种方法都返回相同的结果,可用于索引原始tree列表:

> tree[[z[[7]]]]
[1] 20
> tree[[z2[[7]]]]
[1] 20