Try the following:
funJoeOld <- function(ls) { list_length <- sapply(ls, length) max_length <- max(list_length) lapply(seq_along(ls), function(x) { if (list_length[x] < max_length) { c(ls[[x]], lapply(1:(max_length - list_length[x]), function(y) NA)) } else { ls[[x]] } }) } funJoeOld(list_lists)[[1]] [[1]] [1] 1 [[2]] [1] 2 [[3]] [1] 3 [[4]] [1] NA [[5]] [1] NA [[6]] [1] NA
Edit
I just wanted to highlight how using the right tools in R is of the utmost importance. Although my solution gives the correct results, it is very inefficient. Replacing sapply(ls, length) with lengths , as well as lapply(1:z, function(y) NA) with as.list(rep(NA, z)) , we get almost 15-fold acceleration. Note:
funJoeNew <- function(ls) { list_length <- lengths(ls) max_length <- max(list_length) lapply(seq_along(ls), function(x) { if (list_length[x] < max_length) { c(ls[[x]], as.list(rep(NA, max_length - list_length[x]))) } else { ls[[x]] } }) } funAlistaire <- function(ls) { Map(function(x, y){c(x, rep(NA, y))}, ls, max(lengths(ls)) - lengths(ls)) } fun989 <- function(ls) { lapply(lapply(sapply(ls, unlist), "length<-", max(lengths(ls))), as.list) }
Compare Equality
set.seed(123) samp_list <- lapply(sample(1000, replace = TRUE), function(x) {lapply(1:x, identity)}) ## have to unlist as the NAs in 989 are of the integer ## variety and the NAs in Joe/Alistaire are logical identical(sapply(fun989(samp_list), unlist), sapply(funJoeNew(samp_list), unlist)) [1] TRUE identical(funJoeNew(samp_list), funAlistaire(samp_list)) [1] TRUE
Benchmarks
microbenchmark(funJoeOld(samp_list), funJoeNew(samp_list), fun989(samp_list), funAlistaire(samp_list), times = 30, unit = "relative") Unit: relative expr min lq mean median uq max neval cld funJoeOld(samp_list) 21.825878 23.269846 17.434447 20.803035 18.851403 4.8056784 30 c funJoeNew(samp_list) 1.827741 1.841071 2.253294 1.667047 1.780324 2.4659653 30 ab fun989(samp_list) 3.108230 3.563780 3.170320 3.790048 3.888632 0.9890681 30 b funAli(samp_list) 1.000000 1.000000 1.000000 1.000000 1.000000 1.0000000 30 a
There are two options:
- A good understanding of the
apply family of functions makes for concise and efficient code (as can be seen from the @alistaire and @ 989 solutions). - Understanding the nuances of
base R as a whole can have significant consequences.