如果我有一些R列表mylist,你可以像这样添加一个obj项:
mylist[[length(mylist)+1]] <- obj
但肯定有一些更紧凑的方式。当我刚在R工作时,我试着像这样写lappend():
lappend <- function(lst, obj) {
lst[[length(lst)+1]] <- obj
return(lst)
}
但是,由于R的按名调用语义(lst在调用时被有效地复制,因此对lst的更改在lappend()的作用域之外是不可见的),这当然是行不通的。我知道您可以在R函数中进行环境入侵,从而超出函数的作用域并改变调用环境,但对于编写一个简单的附加函数来说,这似乎是一个巨大的打击。
有谁能提出一个更漂亮的方法吗?如果它对向量和列表都适用,那就更好了。
如果它是一个字符串列表,只需使用c()函数:
R> LL <- list(a="tom", b="dick")
R> c(LL, c="harry")
$a
[1] "tom"
$b
[1] "dick"
$c
[1] "harry"
R> class(LL)
[1] "list"
R>
这也适用于向量,我得到额外的分数了吗?
编辑(2015-02-01):这篇文章即将迎来它的第五个生日。一些好心的读者一直在重复它的缺点,所以无论如何也要看看下面的一些评论。关于列表类型的一个建议:
newlist <- list(oldlist, list(someobj))
一般来说,R类型使得所有类型和用途都很难有一个或只有一个习语。
也许你想要这样的东西?
> push <- function(l, x) {
lst <- get(l, parent.frame())
lst[length(lst)+1] <- x
assign(l, lst, envir=parent.frame())
}
> a <- list(1,2)
> push('a', 6)
> a
[[1]]
[1] 1
[[2]]
[1] 2
[[3]]
[1] 6
这不是一个非常礼貌的函数(分配给parent.frame()有点粗鲁),但IIUYC这是你想要的。
事实上,c()函数有一个微妙之处。如果你有:
x <- list()
x <- c(x,2)
x = c(x,"foo")
如你所料,你将获得:
[[1]]
[1]
[[2]]
[1] "foo"
但是如果你添加一个x <- c(x, matrix(5,2,2))的矩阵,你的列表将有另外4个值为5的元素!
你最好做:
x <- c(x, list(matrix(5,2,2))
它适用于任何其他对象,你将获得预期的:
[[1]]
[1]
[[2]]
[1] "foo"
[[3]]
[,1] [,2]
[1,] 5 5
[2,] 5 5
最后,你的函数变成:
push <- function(l, ...) c(l, list(...))
它适用于任何类型的对象。你可以更聪明地去做:
push_back <- function(l, ...) c(l, list(...))
push_front <- function(l, ...) c(list(...), l)