0

How to append two consecutive items in R list using another list length?

a <- list( "a", "b", "c")
audit <- list()
j <- 0
for (i in 1:length(a)){
 pre <- paste(a[i], "_present")
 nonpre <- paste(a[i], "_non_present")
 i <- j+1
 audit[[i]]<- pre
 j <- i+1
 audit[[j]] <- nonpre
}

Result:audit["a_present, "a_non_present", "b_present", "b_non_present", "c_present", "c_non_present"]

My solution is quite dirty. Any smarter way is appreciated. What are the other ways to append to the list?

alistaire
  • 42,459
  • 4
  • 77
  • 117
ilaunchpad
  • 1,283
  • 3
  • 16
  • 32

4 Answers4

1

You can use outer :

outer(a, c('_present', '_non_present'), paste0)

#           [,1]        [,2]           
#[1,] "a_present" "a_non_present"
#[2,] "b_present" "b_non_present"
#[3,] "c_present" "c_non_present"

If you want output as a list :

as.list(t(outer(a, c('_present', '_non_present'), paste0)))


#[[1]]
#[1] "a_present"

#[[2]]
#[1] "a_non_present"

#[[3]]
#[1] "b_present"

#[[4]]
#[1] "b_non_present"

#[[5]]
#[1] "c_present"

#[[6]]
#[1] "c_non_present"
Ronak Shah
  • 377,200
  • 20
  • 156
  • 213
0

You can use purrr::map to create those tuples of one element from a, concatenated with _present' & '_not_present', then just unlist` the result to get one vector :)

library(purrr)

a <- list("a", "b", "c")
unlist(purrr::map(a, function(i){paste0(i, c('_present','_not_present'))}))

This gives you the desired output in a vector:

[1] "a_present"     "a_not_present" "b_present"     "b_not_present" "c_present"     "c_not_present"
alex_jwb90
  • 1,663
  • 1
  • 11
  • 20
0

You can use sapply. Here I've used paste0 instead of paste.

as.list(sapply(a, function(i) paste0(i, c('_present','_non_present'))))

[[1]]
[1] "a_present"

[[2]]
[1] "a_non_present"

[[3]]
[1] "b_present"

[[4]]
[1] "b_non_present"

[[5]]
[1] "c_present"

[[6]]
[1] "c_non_present"
Edward
  • 10,360
  • 2
  • 11
  • 26
0

You can use sapply and Reduce to obtain a simple vector:

Reduce(`c`, sapply(a, function(x) paste0(x, c('_present','_not_present'))))

Output

[1] "a_present"     "a_not_present" "b_present"     "b_not_present" "c_present"     "c_not_present

Update

After having realized that my solulion is likely slow as hell, I added two more functions and benchmarked:

fun1 <- function(y) Reduce(`c`, sapply(y, function(x) paste0(x, c('_prfun1 <- function(y) Reduce(`c`, sapply(y, function(x) paste0(x, c('_present','_not_present'))))
fun2 <- function(y) unlist(purrr::map(y, function(i){paste0(i, c('_present','_not_present'))}))
fun3 <- function(y) as.list(sapply(y, function(i) paste0(i, c('_present','_non_present'))))
fun4 <- function(y) array(sapply(y, function(x) paste0(x, c('_present','_not_present'))))
fun5 <- function(y) as.vector(sapply(y, function(x) paste0(x, c('_present','_not_present'))))

fun6 <- function(y){
audit <- list()
j <- 0
for (i in 1:length(y)){
  pre <- paste(y[i], "_present")
  nonpre <- paste(y[i], "_non_present")
  i <- j+1
  audit[[i]]<- pre
  j <- i+1
  audit[[j]] <- nonpre
}
audit
}


x <- list(sample(letters, 1000, replace = TRUE))
microbenchmark::microbenchmark(fun1(x), fun2(x), fun3(x), fun4(x), fun5(x), fun6(x), times = 10L)

Results

    Unit: microseconds
    expr      min       lq      mean    median       uq      max neval
 fun1(x) 2886.633 3107.855 3673.7590 3191.4295 3965.469 6969.991    10
 fun2(x)  225.562  235.774  553.8192  277.9055  407.876 2839.410    10
 fun3(x)  237.601  245.103  643.7252  261.1835  407.830 3840.739    10
 fun4(x)  222.445  230.426  533.4771  249.6535  261.322 3075.166    10
 fun5(x)  219.845  232.682  508.5585  253.7870  298.801 2775.606    10
 fun6(x) 1531.715 1597.888 2229.4907 1616.1170 1913.850 7245.782    10

fun2 - fun5 have roughly the same speed, fun4 and fun5 being slightly faster. The original solution is (unexpectedly) slow.

slava-kohut
  • 4,203
  • 1
  • 7
  • 24
  • 1
    Nice work. I assumed the OP wanted a list similar to their `audit` as the output. The fact that `Reduce` is slow is very interesting though. – Edward Jul 09 '20 at 00:38
  • 1
    @Edward function calls in R can be computationally expensive, particulartly when new objects are created (I know this from experience). This is why I expected the `Reduce` solution to be slow. – slava-kohut Jul 09 '20 at 01:03