If I have some R list mylist
, you can append an item obj
to it like so:
mylist[[length(mylist)+1]] <- obj
But surely there is some more compact way. When I was new at R, I tried writing lappend()
like so:
lappend <- function(lst, obj) {
lst[[length(lst)+1]] <- obj
return(lst)
}
but of course that doesn't work due to R's call-by-name semantics (lst
is effectively copied upon call, so changes to lst
are not visible outside the scope of lappend()
. I know you can do environment hacking in an R function to reach outside the scope of your function and mutate the calling environment, but that seems like a large hammer to write a simple append function.
Can anyone suggest a more beautiful way of doing this? Bonus points if it works for both vectors and lists.
If it's a list of string, just use the
c()
function :That works on vectors too, so do I get the bonus points?
Edit (2015-Feb-01): This post is coming up on its fifth birthday. Some kind readers keep repeating any shortcomings with it, so by all means also see some of the comments below. One suggestion for
list
types:In general, R types can make it hard to have one and just one idiom for all types and uses.
try this function lappend
and other suggestions from this page Add named vector to a list
Bye.
There is also
list.append
from therlist
(link to the documentation)It's very simple and efficient.
You want something like this maybe?
It's not a very polite function (assigning to
parent.frame()
is kind of rude) but IIUYC it's what you're asking for.Not sure why you don't think your first method won't work. You have a bug in the lappend function: length(list) should be length(lst). This works fine and returns a list with the appended obj.
For validation I ran the benchmark code provided by @Cron. There is one major difference (in addition to running faster on the newer i7 processor): the
by_index
now performs nearly as well as thelist_
:For reference here is the benchmark code copied verbatim from @Cron's answer (just in case he later changes the contents):