簡體   English   中英

索引嵌套列表/環境的有效(或最有效)方法是什么?

[英]What's an efficient (or the most efficient) way to index nested lists/environments?

我喜歡上下文中列表的靈活性,其中正式類的對象太不靈活。 基本上,它們可用於映射我們在操作系統的標准文件系統中處理我們概念上使用的樹結構的方式。

然而,為了掌握超過3或4的“嵌套度”,您需要一種計算嵌套列表索引的方法。 一旦你有了這樣的索引,選擇一個特定的分支,更新它,在列表中添加新的分支並不是很困難,簡而言之:做我們在操作系統文件系統中對文件和文件夾做的所有事情。

基本上, str(object)已經完成了工作,但只輸出文本( capture.output(str(object)) 。我將其轉換為數據框結構

示例列表

setClass("TESTCLASS_X", representation=representation(a="numeric"))
setRefClass("TESTCLASS_Y", fields=list(a="numeric"))

src <- list(
    a=list(
        a.1=list(a.1.1 = 1, a.1.2 = 1:5, a.1.3 = integer(0)),
        a.2=list(a.2.1="a", a.2.2=c("a", "b", "c", "d", "e"), a.2.3=character()),
        a.3=list(a.3.1=1.5, a.3.2=c(1.5, 2.5), a.3.3=numeric()), 
        a.4=list(a.4.1=1+1i, a.4.2=c(0.1+0.3i, 0.2+0.2i, 0.1+0.1i), a.4.3=complex()),  
        a.5=list(a.5.1 = TRUE, a.5.2 = c(TRUE, TRUE, TRUE), a.5.3 = logical())
    ), 
    b=list(
        b.1=list(
            b.1.1=list(b.1.1.1 =matrix(1, ncol=1),
                b.1.1.2=matrix(c(1:4), ncol=2, dimnames=list(NULL, c("a","b"))),
                b.1.1.3=matrix()
            ),
            b.1.2=list(b.1.2.1=data.frame(1), b.1.2.2=data.frame(a=1:3, b=1:3),
                b.1.2.3=data.frame() 
            )
        ),
        b.2=list(
            b.2.1=list(b.2.1.1=list(a=1), b.2.1.2=list(a=1:2, b=letters[1:2]),
                b.2.1.3=list(a=1:2, b="a", c=1:3, d=FALSE, e=1:5), b.2.1.4=list()
            )
        )
    ),
    c=list(
        c.1=list(c.1.1=new.env(), c.1.2=new("TESTCLASS_X", a=1:5), 
            c.1.3=new("TESTCLASS_Y", a=1:5))
    )
)

期望的輸出

                    name pos is.top is.bottom       class is.s4  dim
1                      a   1   TRUE     FALSE        list FALSE    5
2                  a/a.1   2  FALSE     FALSE        list FALSE    3
3            a/a.1/a.1.1   3  FALSE      TRUE     numeric FALSE    1
4            a/a.1/a.1.2   3  FALSE      TRUE     integer FALSE    5
5            a/a.1/a.1.3   3  FALSE      TRUE     integer FALSE    0
6                  a/a.2   2  FALSE     FALSE        list FALSE    3
7            a/a.2/a.2.1   3  FALSE      TRUE   character FALSE    1
8            a/a.2/a.2.2   3  FALSE      TRUE   character FALSE    5
9            a/a.2/a.2.3   3  FALSE      TRUE   character FALSE    0
10                 a/a.3   2  FALSE     FALSE        list FALSE    3
11           a/a.3/a.3.1   3  FALSE      TRUE     numeric FALSE    1
12           a/a.3/a.3.2   3  FALSE      TRUE     numeric FALSE    2
13           a/a.3/a.3.3   3  FALSE      TRUE     numeric FALSE    0
14                 a/a.4   2  FALSE     FALSE        list FALSE    3
15           a/a.4/a.4.1   3  FALSE      TRUE     complex FALSE    1
16           a/a.4/a.4.2   3  FALSE      TRUE     complex FALSE    3
17           a/a.4/a.4.3   3  FALSE      TRUE     complex FALSE    0
18                 a/a.5   2  FALSE     FALSE        list FALSE    3
19           a/a.5/a.5.1   3  FALSE      TRUE     logical FALSE    1
20           a/a.5/a.5.2   3  FALSE      TRUE     logical FALSE    3
21           a/a.5/a.5.3   3  FALSE      TRUE     logical FALSE    0
22                     b   1   TRUE     FALSE        list FALSE    2
23                 b/b.1   2  FALSE     FALSE        list FALSE    2
24           b/b.1/b.1.1   3  FALSE     FALSE        list FALSE    3
25   b/b.1/b.1.1/b.1.1.1   4  FALSE      TRUE      matrix FALSE  1-1
26   b/b.1/b.1.1/b.1.1.2   4  FALSE      TRUE      matrix FALSE  2-2
27   b/b.1/b.1.1/b.1.1.3   4  FALSE      TRUE      matrix FALSE  1-1
28           b/b.1/b.1.2   3  FALSE     FALSE        list FALSE    3
29   b/b.1/b.1.2/b.1.2.1   4  FALSE      TRUE  data.frame FALSE  1-1
30   b/b.1/b.1.2/b.1.2.2   4  FALSE      TRUE  data.frame FALSE  3-2
31   b/b.1/b.1.2/b.1.2.3   4  FALSE      TRUE  data.frame FALSE  0-0
32                 b/b.2   2  FALSE     FALSE        list FALSE    1
33           b/b.2/b.2.1   3  FALSE     FALSE        list FALSE    4
34   b/b.2/b.2.1/b.2.1.1   4  FALSE     FALSE        list FALSE    1
35 b/b.2/b.2.1/b.2.1.1/a   5  FALSE      TRUE     numeric FALSE    1
36   b/b.2/b.2.1/b.2.1.2   4  FALSE     FALSE        list FALSE    2
37 b/b.2/b.2.1/b.2.1.2/a   5  FALSE      TRUE     integer FALSE    2
38 b/b.2/b.2.1/b.2.1.2/b   5  FALSE      TRUE   character FALSE    2
39   b/b.2/b.2.1/b.2.1.3   4  FALSE     FALSE        list FALSE    5
40 b/b.2/b.2.1/b.2.1.3/a   5  FALSE      TRUE     integer FALSE    2
41 b/b.2/b.2.1/b.2.1.3/b   5  FALSE      TRUE   character FALSE    1
42 b/b.2/b.2.1/b.2.1.3/c   5  FALSE      TRUE     integer FALSE    3
43 b/b.2/b.2.1/b.2.1.3/d   5  FALSE      TRUE     logical FALSE    1
44 b/b.2/b.2.1/b.2.1.3/e   5  FALSE      TRUE     integer FALSE    5
45   b/b.2/b.2.1/b.2.1.4   4  FALSE     FALSE        list FALSE    0
46                     c   1   TRUE     FALSE        list FALSE    1
47                 c/c.1   2  FALSE     FALSE        list FALSE    3
48           c/c.1/c.1.1   3  FALSE      TRUE environment FALSE <NA>
49           c/c.1/c.1.2   3  FALSE      TRUE TESTCLASS_X  TRUE    1
50           c/c.1/c.1.3   3  FALSE      TRUE TESTCLASS_Y  TRUE    1

編輯2011-11-21

Spacedman問我,這不僅僅是深度優先搜索的結果。 嗯,肯定是,但是

  1. 我掙扎着它的遞歸本質
  2. 我認為“手動”深度優先可能總是比依賴capture.output(str()更低效,因為它基於C(IIRC)

這與我的第一個深度優先方法類似:

src取自上面

objIndex <- function(src){
    out <- lapply(1:length(src), function(x){
        if(class(src[[x]]) == "list"){
            if(length(src[[x]])){
                df.1 <- objIndex(src=src[[x]])
            } else {
                df.1 <- data.frame(
                    path=names(src[x]),
                    pos=NA,
                    is.top=FALSE,
                    is.bottom=TRUE,
                    class=class(src[[x]]),
                    dim=length(src[[x]])
                )    
            }
        } else {
            df.1 <- data.frame(
                path=ifelse(is.null(names(src[x])), NA, names(src[x])),
                pos=NA,
                is.top=FALSE,
                is.bottom=TRUE,
                class=class(src[[x]]),
                dim=length(src[[x]])
            )    
        }  
        df.1
    })
    return(out)
}
> objIndex(src, df=NULL)
[[1]]
[[1]][[1]]
[[1]][[1]][[1]]
   path pos is.top is.bottom   class dim
1 a.1.1  NA  FALSE      TRUE numeric   1

[[1]][[1]][[2]]
   path pos is.top is.bottom   class dim
1 a.1.2  NA  FALSE      TRUE integer   5

[[1]][[1]][[3]]
   path pos is.top is.bottom   class dim
1 a.1.3  NA  FALSE      TRUE integer   0


[[1]][[2]]
[[1]][[2]][[1]]
   path pos is.top is.bottom     class dim
1 a.2.1  NA  FALSE      TRUE character   1

[[1]][[2]][[2]]
   path pos is.top is.bottom     class dim
1 a.2.2  NA  FALSE      TRUE character   5

[[1]][[2]][[3]]
   path pos is.top is.bottom     class dim
1 a.2.3  NA  FALSE      TRUE character   0


[[1]][[3]]
[[1]][[3]][[1]]
   path pos is.top is.bottom   class dim
1 a.3.1  NA  FALSE      TRUE numeric   1

[[1]][[3]][[2]]
   path pos is.top is.bottom   class dim
1 a.3.2  NA  FALSE      TRUE numeric   2

[[1]][[3]][[3]]
   path pos is.top is.bottom   class dim
1 a.3.3  NA  FALSE      TRUE numeric   0


[[1]][[4]]
[[1]][[4]][[1]]
   path pos is.top is.bottom   class dim
1 a.4.1  NA  FALSE      TRUE complex   1

[[1]][[4]][[2]]
   path pos is.top is.bottom   class dim
1 a.4.2  NA  FALSE      TRUE complex   3

[[1]][[4]][[3]]
   path pos is.top is.bottom   class dim
1 a.4.3  NA  FALSE      TRUE complex   0


[[1]][[5]]
[[1]][[5]][[1]]
   path pos is.top is.bottom   class dim
1 a.5.1  NA  FALSE      TRUE logical   1

[[1]][[5]][[2]]
   path pos is.top is.bottom   class dim
1 a.5.2  NA  FALSE      TRUE logical   3

[[1]][[5]][[3]]
   path pos is.top is.bottom   class dim
1 a.5.3  NA  FALSE      TRUE logical   0



[[2]]
[[2]][[1]]
[[2]][[1]][[1]]
[[2]][[1]][[1]][[1]]
     path pos is.top is.bottom  class dim
1 b.1.1.1  NA  FALSE      TRUE matrix   1

[[2]][[1]][[1]][[2]]
     path pos is.top is.bottom  class dim
1 b.1.1.2  NA  FALSE      TRUE matrix   4

[[2]][[1]][[1]][[3]]
     path pos is.top is.bottom  class dim
1 b.1.1.3  NA  FALSE      TRUE matrix   1


[[2]][[1]][[2]]
[[2]][[1]][[2]][[1]]
     path pos is.top is.bottom      class dim
1 b.1.2.1  NA  FALSE      TRUE data.frame   1

[[2]][[1]][[2]][[2]]
     path pos is.top is.bottom      class dim
1 b.1.2.2  NA  FALSE      TRUE data.frame   2

[[2]][[1]][[2]][[3]]
     path pos is.top is.bottom      class dim
1 b.1.2.3  NA  FALSE      TRUE data.frame   0



[[2]][[2]]
[[2]][[2]][[1]]
[[2]][[2]][[1]][[1]]
[[2]][[2]][[1]][[1]][[1]]
   path pos is.top is.bottom   class dim
1 <<1>>  NA  FALSE      TRUE numeric   1


[[2]][[2]][[1]][[2]]
[[2]][[2]][[1]][[2]][[1]]
  path pos is.top is.bottom   class dim
1    a  NA  FALSE      TRUE integer   2

[[2]][[2]][[1]][[2]][[2]]
  path pos is.top is.bottom     class dim
1    b  NA  FALSE      TRUE character   2


[[2]][[2]][[1]][[3]]
[[2]][[2]][[1]][[3]][[1]]
   path pos is.top is.bottom   class dim
1 <<1>>  NA  FALSE      TRUE integer   2

[[2]][[2]][[1]][[3]][[2]]
   path pos is.top is.bottom     class dim
1 <<2>>  NA  FALSE      TRUE character   1

[[2]][[2]][[1]][[3]][[3]]
   path pos is.top is.bottom   class dim
1 <<3>>  NA  FALSE      TRUE integer   3

[[2]][[2]][[1]][[3]][[4]]
   path pos is.top is.bottom   class dim
1 <<4>>  NA  FALSE      TRUE logical   1

[[2]][[2]][[1]][[3]][[5]]
   path pos is.top is.bottom   class dim
1 <<5>>  NA  FALSE      TRUE integer   5


[[2]][[2]][[1]][[4]]
     path pos is.top is.bottom class dim
1 b.2.1.4  NA  FALSE      TRUE  list   0




[[3]]
[[3]][[1]]
[[3]][[1]][[1]]
   path pos is.top is.bottom       class dim
1 c.1.1  NA  FALSE      TRUE environment   0

[[3]][[1]][[2]]
   path pos is.top is.bottom       class dim
1 c.1.2  NA  FALSE      TRUE TESTCLASS_X   1

[[3]][[1]][[3]]
   path pos is.top is.bottom       class dim
1 c.1.3  NA  FALSE      TRUE TESTCLASS_Y   1

可以用rapply獲得部分解決方案。 這只計算結束節點的值,因此您獲得數據框中is.bottomTRUE 獲取表的其余部分應該可以通過檢查名稱,但我懷疑它很費勁,而且這些節點相當無聊(所有只是class = "list"is.S4 = FALSE )。

classis.S4列很容易獲得。

out_class <- rapply(src, class)    
out_isS4 <- rapply(src, isS4) 

我不太確定你在使用dim列時做了什么,但類似的調用應該讓你開始。

out_dim <- rapply(src, length)

如果你想要它們的名字,我們使用你想要斜線分隔符的技巧,其中有一個點后跟一個字母。 如果你在列表中沒有命名元素,這可能會破壞,雖然我沒有測試過。

sep <- "/"
out_name <- gsub("\\.(?=[[:alpha:]])", sep, names(out_class), perl = TRUE)

同樣,嵌套的深度可以從剛添加到名稱的斜杠數中找到。

out_pos <- sapply(strsplit(out_name, sep), length) 

最后,我們將這些組合成一個數據框。

(out <- data.frame(
  name = out_name,
  pos = out_pos,
  class = out_class,
  is.S4 = out_isS4,
  dim = out_dim  
))

經過兩次糟糕的嘗試后,我想出了這里發布的那個。 但它仍然覺得這太復雜了,而且可以更容易實現。

對於混亂的格式我很抱歉! 我會在幾天內將代碼移動到Github倉庫。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM