How to merge 2 vectors alternating indexes?

RVectorMerge

R Problem Overview


I would like to merge 2 vectors this way :

a = c(1,2,3)
b = c(11,12,13)
merged vector : c(1,11,2,12,3,13)

How could I do it ?

R Solutions


Solution 1 - R

This will work using rbind :

c(rbind(a, b))

For example:

a = c(1,2,3)
b = c(11,12,13)

c(rbind(a,b))

#[1]  1 11  2 12  3 13 

Solution 2 - R

The rbind() answer by @jalapic is excellent. Here's an alternative that creates a new vector then assigns the alternating values to it.

a <- c(1,2,3)
b <- c(11,12,13)

x <- vector(class(a), length(c(a, b)))
x[c(TRUE, FALSE)] <- a
x[c(FALSE, TRUE)] <- b
x
# [1]  1 11  2 12  3 13

And one more that shows append

c(sapply(seq_along(a), function(i) append(a[i], b[i], i)))
# [1]  1 11  2 12  3 13

Solution 3 - R

Just wanted to add a simpler solution that works for when vectors are unequal length and you want to append the extra data to the end.

> a <- 1:3
> b <- 11:17
> c(a, b)[order(c(seq_along(a)*2 - 1, seq_along(b)*2))]
 [1]  1 11  2 12  3 13 14 15 16 17

Explanation:

  • c(a, b) creates a vector of the values in a and b.
  • seq_along(a)*2 - 1 creates a vector of the first length(a) odd numbers.
  • seq_along(b)*2 creates a vector of the first length(b) even numbers.
  • order(...) will return the indexes of the numbers in the two seq_along vectors such that x[order(x)] is an ordered list. Since the first seq_along contains the even numbers and the second seq_along has the odds, order will take the first element from the first seq_along, then the first elements of the second seq_along, then the second element from the first seq_along, etc. interspersing the two vector indexes and leaving the extra data at the tail.
  • By indexing c(a, b) using the order vector, we will intersperse a and b.

As a note, since seq_along returns numeric(0) when the input is NULL this solution works even if one of the vectors is length 0.

Solution 4 - R

I had to solve a similar problem, but my vectors were of unequal length. And, I didn't want to recycle the shorter vector, but just append the tail of the longer vector.

And the solution for @RichardScriven didn't work for me (though I may have done something wrong and didn't try hard to troubleshoot).

Here is my solution:

#' Riffle-merges two vectors, possibly of different lengths
#'
#' Takes two vectors and interleaves the elements.  If one vector is longer than
#' the other, it appends on the tail of the longer vector to the output vector.
#' @param a First vector
#' @param b Second vector
#' @return Interleaved vector as described above.
#' @author Matt Pettis
riffle <- function(a, b) {
  len_a <- length(a)
  len_b <- length(b)
  len_comm <- pmin(len_a, len_b)
  len_tail <- abs(len_a - len_b)

  if (len_a < 1) stop("First vector has length less than 1")
  if (len_b < 1) stop("Second vector has length less than 1")

  riffle_common <- c(rbind(a[1:len_comm], b[1:len_comm]))
  
  if (len_tail == 0) return(riffle_common)

  if (len_a > len_b) {
    return(c(riffle_common, a[(len_comm + 1):len_a]))
  } else {
    return(c(riffle_common, b[(len_comm + 1):len_b]))
  }
}

# Try it out
riffle(1:7, 11:13)
  [1]  1 11  2 12  3 13  4  5  6  7

riffle(1:3, 11:17)
   [1]  1 11  2 12  3 13 14 15 16 17

HTH, Matt

Solution 5 - R

@MBo's answer to my question at https://stackoverflow.com/a/58773002/2556061 implies a solution for evenly interlacing vectors of unequal length. I'm reporting it here in for reference.

interleave <- function(x, y)
{
  m <- length(x)
  n <- length(y)
  xi <- yi <- 1
  len <- m + n
  err <- len %/% 2
  res <- vector()
  for (i in 1:len)
  {
    err <- err - m
    if (err < 0)
    {
      
      res[i] <- x[xi]
      xi <- xi + 1
      err <- err + len
    } else
    {
       res[i] <- y[yi]
      yi <- yi + 1
     }
  }
  res
}

gives

interleave(1:10, 100:120)

c(100, 1, 101, 102, 2, 103, 104, 3, 105, 106, 4, 107, 108, 5, 109, 110, 111, 6, 112, 113, 7, 114, 115, 8, 116, 117, 9, 118, 119, 10, 120)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionWiceloView Question on Stackoverflow
Solution 1 - RjalapicView Answer on Stackoverflow
Solution 2 - RRich ScrivenView Answer on Stackoverflow
Solution 3 - RBarkerView Answer on Stackoverflow
Solution 4 - RmpettisView Answer on Stackoverflow
Solution 5 - RmschauerView Answer on Stackoverflow