# Match a vector inside a vector

• A+
Category：Languages

I have:

vec1 <- c(0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1) vec2 <- c(1, 1)

I expect:

magicFUN(x = vec1, y = vec2) [1] 4 7 8

That means that I want the position of a complete vector inside another vector. match and is.element were not useful because they return the position of each element of vec2 and I need that magicFUN matches the complete vec2 into vec1.

A general solution:

magicFUN <- function(vec1, vec2) {   if(length(vec2) > length(vec1)) stop("vec 2 should be shorter")   len <- length(vec1) - length(vec2) + 1   out <- vector(mode = "logical", length=len)        for(i in 1:len) {     out[i] <- identical(vec2, vec1[i:(i+length(vec2)-1)])   }   return(which(out)) }  vec1 <- c(0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1) vec2 <- c(1, 1)  magicFUN(vec1, vec2)  [1] 4 7 8

A for loop will be the fastest solution (besides using Rcpp). See benchmarks below:

magicFUN <- function(vec1, vec2) {   if(length(vec2) > length(vec1)) stop("vec 2 should be shorter")   len <- length(vec1) - length(vec2) + 1   out <- vector(mode = "logical", length=len)        for(i in 1:len) {     out[i] <- identical(vec2, vec1[i:(i+length(vec2)-1)])   }   return(which(out)) }  magicFUN2 <- function(vec1, vec2){   l1 <- length(vec1)   l2 <- length(vec2)   which(colSums(sapply(1:(l1-l2), function(i) vec1[i:(i+l2-1)]) == vec2) == l2) }  magicFUN3 <- function(vec1, vec2){   which(c(zoo::rollapply(vec1, width=length(vec2),                      function(x)all(x==vec2), align = "left"),rep(FALSE,length(vec2)-1))==TRUE) }  library(microbenchmark) microbenchmark(magicFUN(vec1, vec2), magicFUN2(vec1, vec2), magicFUN3(vec1, vec2))  Unit: milliseconds                   expr       min        lq      mean    median        uq       max neval cld   magicFUN(vec1, vec2)  6.083572  6.575844  7.292443  6.878016  7.421208  13.35746   100  a   magicFUN2(vec1, vec2)  8.289640  8.976736 11.007967  9.338644  9.951492 139.68886   100  a   magicFUN3(vec1, vec2) 39.131268 42.369479 46.303722 44.203563 45.053252 172.46151   100   b