2011-09-20 167 views
7

我正在將一個函數應用於列表的元素。如何在列表中循環並訪問名稱和屬性?

列表有names,所以從某種意義上說,每個元素都有自己的名字,但是如果lapply函數已經從列表中提取/分離元素,我該如何訪問它?

一些虛構的數據(如內部功能我在這裏濫用dput):

r <- list(a=structure(1:4, unit="test"), b='abc') 
lapply(r, dput) 

我看到這裏是dput接收列表中的對象,就好像與[[訪問,剝奪了名的,他們在包含列表中。

所以我想我會放棄使用apply家族的函數並寫一個循環的想法,但我並不特別喜歡這個想法,它迫使我構造完整函數的結果。

result <- list() 
for (name in names(r)) { 
    print(name) 
    result[[name]] <- dput(r[[name]]) 
} 
result 

任何有洞察力的想法?

回答

5

您可以模擬循環後面的想法,同時仍然使用lapply,方法是將數字向量傳遞到lapply,然後使用該向量作爲索引從所需列表中提取元素。這可能是沒有意義的,但希望例子說明我的意思:

lapply(seq_along(r), function(i)dput(r[i])) 

structure(list(a = structure(1:4, unit = "test")), .Names = "a") 
structure(list(b = "abc"), .Names = "b") 
[[1]] 
[[1]]$a 
[1] 1 2 3 4 
attr(,"unit") 
[1] "test" 



[[2]] 
[[2]]$b 
[1] "abc" 

的核心思想是,seq_along(x)返回相同長度x的序列。例如:

> seq_along(r) 
[1] 1 2 

有關更多詳細信息,請參閱?seq_along


編輯

這似乎是非常略高於索引更快的名字:

library(rbenchmark) 
benchmark(
    xx <- lapply(names(r), function(i)dput(r[i])), 
    yy <- lapply(seq_along(r), function(i)dput(r[i])), 
    replications=10000) 

               test replications elapsed relative user.self 
1  xx <- lapply(names(r), function(i) dput(r[i]))  10000 1.95 1.026316  1.70 
2 yy <- lapply(seq_along(r), function(i) dput(r[i]))  10000 1.90 1.000000  1.66 
    sys.self user.child sys.child 
1  0.00   NA  NA 
2  0.01   NA  NA 
+0

是通過數字索引更快訪問比按名稱訪問? – mariotomo

+0

好的,它比循環更具可讀性,避免了額外的'result'變量的需要。所以我按照你的提示,謝謝!這裏只有變化是我更喜歡'lapply(名字(r),函數(名字)dput(r [[名字])))''。我等待接受答案,看看是否有更多想法出現。 – mariotomo

+0

只**很**。我已經用一些'rbenchmark'結果編輯了我的答案 – Andrie

2

你可以使用mapply

dummy <- function(value, name) { 
    list(
     name_of_element = name, 
     value_of_element = value 
    ) 
} 
str(mapply(dummy, r, names(r), SIMPLIFY=FALSE)) 
# List of 2 
# $ a:List of 2 
    # ..$ name_of_element : chr "a" 
    # ..$ value_of_element: atomic [1:4] 1 2 3 4 
    # .. ..- attr(*, "unit")= chr "test" 
# $ b:List of 2 
    # ..$ name_of_element : chr "b" 
    # ..$ value_of_element: chr "abc" 
+1

不太確定是否可讀性更高,但速度比這裏慢了70%:'library(rbenchmark); benchmark( xx < - lapply(names(r),function(i)all(r [[i]] == 0)), yy < - lapply(seq_along(r),function(i)all (函數(i,n)全部(i == 0),r,名稱(r),SIMPLIFY = FALSE), 複製= 10000) – mariotomo