Если у меня есть некоторый список 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>
Это работает и для векторов, так что получу ли я бонусные очки?
Edit (2015-Feb-01): Этому посту исполняется пять лет. Некоторые добрые читатели продолжают повторять любые недостатки в нем, так что непременно ознакомьтесь также с некоторыми комментариями ниже. Одно предложение по поводу list
типов:
newlist <- list(oldlist, list(someobj))
В целом, типы R могут затруднить создание одной и только одной идиомы для всех типов и применений.
Это простой способ добавить элементы в список R:
# create an empty list:
small_list = list()
# now put some objects in it:
small_list$k1 = "v1"
small_list$k2 = "v2"
small_list$k3 = 1:10
# retrieve them the same way:
small_list$k1
# returns "v1"
# "index" notation works as well:
small_list["k2"]
Или программно:
kx = paste(LETTERS[1:5], 1:5, sep="")
vx = runif(5)
lx = list()
cn = 1
for (itm in kx) { lx[itm] = vx[cn]; cn = cn + 1 }
print(length(lx))
# returns 5
Если вы передадите переменную списка в виде строки в кавычках, вы сможете получить доступ к ней из функции, например:
push <- function(l, x) {
assign(l, append(eval(as.name(l)), x), envir=parent.frame())
}
так:
> a <- list(1,2)
> a
[[1]]
[1] 1
[[2]]
[1] 2
> push("a", 3)
> a
[[1]]
[1] 1
[[2]]
[1] 2
[[3]]
[1] 3
>
или за дополнительную плату:
> v <- vector()
> push("v", 1)
> v
[1] 1
> push("v", 2)
> v
[1] 1 2
>
Вы хотите что-то вроде этого?
> 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 это то, что вы просите.