2011-09-20 121 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