如何在列表中循环并访问名称和属性?
问题描述:
我正在将一个函数应用于列表的元素。如何在列表中循环并访问名称和属性?
列表有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
任何有洞察力的想法?
答
您可以模拟循环后面的想法,同时仍然使用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
答
你可以使用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 mariotomo
是通过数字索引更快访问比按名称访问? – mariotomo
好的,它比循环更具可读性,避免了额外的'result'变量的需要。所以我按照你的提示,谢谢!这里只有变化是我更喜欢'lapply(名字(r),函数(名字)dput(r [[名字])))''。我等待接受答案,看看是否有更多想法出现。 – mariotomo
只**很**。我已经用一些'rbenchmark'结果编辑了我的答案 – Andrie