Search code examples
rstringvectorconcatenation

Interlacing two vectors


Suppose I have two vectors defined as follows:

a <- c("a1", "a2", "a3")
b <- c("b1", "b2", "b3")

Now I want to end up with a string vector like this one:

c("a1","b1", "a2", "b2", "a3", "b3")

Is this possible?


Solution

  • You can rbind them, then coerce back to a vector.

    a <- c("a1", "a2", "a3") 
    b <- c("b1", "b2", "b3")
    c(rbind(a,b))
    
    # [1] "a1" "b1" "a2" "b2" "a3" "b3"
    

    As @Moody_Mudskipper points out, as.vector(rbind(a,b))) is faster

    For the case when the lengths are different, I found the following solution from Rolf Turner at this link: http://r.789695.n4.nabble.com/Interleaving-elements-of-two-vectors-td795123.html

    riffle <- function (a,b) { 
      n  <- min(length(a),length(b)) 
      p1 <- as.vector(rbind(a[1:n],b[1:n])) 
      p2 <- c(a[-(1:n)],b[-(1:n)]) 
      c(p1,p2) 
    } 
    
    riffle(1:3, letters[1:5])
    
    # [1] "1" "a" "2" "b" "3" "c" "d" "e"
    

    There is also vctrs::vec_interleave()

    a <- paste0("a", seq(1e6))
    b <- paste0("b", seq(1e6))
    
    bench::mark(
      rbind = as.vector(rbind(a,b)),
      vec_interleave = vctrs::vec_interleave(a, b),
      mm1 = c(matrix(c(a,b),ncol=length(a),,T)),
      mm2 = c(a,b)[rep(1:length(a),each=2)+c(0,length(a))],
      mm3 = c(mapply(c,a,b)),
    )
    #> Warning: Some expressions had a GC in every iteration; so filtering is disabled.
    #> # A tibble: 5 × 6
    #>   expression          min   median `itr/sec` mem_alloc `gc/sec`
    #>   <bch:expr>     <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
    #> 1 rbind              22ms   57.6ms     21.9     30.5MB    11.9 
    #> 2 vec_interleave   33.6ms   35.1ms     13.1     22.9MB     3.75
    #> 3 mm1              61.7ms   70.2ms     12.8     45.8MB     5.48
    #> 4 mm2              68.8ms  103.7ms      9.98    64.8MB     8.32
    #> 5 mm3             884.3ms  884.3ms      1.13      69MB     3.39
    

    Created on 2023-11-24 with reprex v2.0.2