A better way to push and pop to/from lists in R?
A few years late to the party, but here's the approach that requires the least amount of typing. Note that pop
removes the last element from the object.
push <- function(obj, input) {
variable <- deparse(substitute(obj))
out <- get(variable, envir = parent.frame(n=2))
out[[length(out)+1]] <- input
assign(variable, out, envir = parent.frame(n=2))
}
pop <- function(obj) {
variable <- deparse(substitute(obj))
obj <- get(variable, envir = parent.frame(n=2))
if (length(obj) > 0) {
out <- obj[[length(obj)]]
assign(variable, obj[-length(obj)], envir = parent.frame(n=2))
}else{
out <- NULL
assign(variable, out, envir = parent.frame(n=2))
}
return(out)
}
Example:
> foo <- list()
> push(foo, "a")
> push(foo, "b")
> foo
[[1]]
[1] "a"
[[2]]
[1] "b"
> pop(foo)
[1] "b"
> foo
[[1]]
[1] "a"
pushR = function(foo, bar){
foo[[length(foo)+1]] <- bar
foo
}
popR=function(foo){
foo[[length(foo)]]
}
foo <- list()
for (i in 1:10) {
x <- data.frame(a=i, b=rnorm(1,0,1))
foo <- pushR(foo, x)
}
popR(foo)
foo[[length(foo)+1]] <- bar
could be rewritten as
foo <- append(foo, bar)
and
bar <- foo[[length(foo)]]
could be rewritten as
bar <- tail(foo,1)
Note that with functional languages such as R functions generally aren't supposed to changes values of parameters passed to them; typically you return a new object which you can assign elsewhere. The function should have no "side effects." Functions like push/pop
in other languages usually modify one of the passed parameters.