Match all elements of a pattern with a vector and in the same order

Viewed 86

I created a function yes.seq that takes two arguments, a pattern pat and data dat. The function looks for the presence of a pattern in the data and in the same sequence

for example

dat <- letters[1:10]
dat
[1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"
pat <- c('a',"c","g")
 
yes.seq(pat = pat,dat = dat)
# [1] TRUE

because this sequence is in the pattern and in the same order

"a" "b" "c" "d" "e" "f" "g" "h" "i" "j"

If, for example, 'dat' is reversed, then we get FALSE:

yes.seq(pat = pat, dat = rev(dat))
# [1] FALSE

Here is my function

yes.seq <- function(pat , dat){  
  lv <- rep(F,length(pat))
  k <- 1     
  for(i in 1:length(dat)){        
            if(dat[i] == pat[k]) 
              {
              lv[k] <- TRUE
              k <- k+1 
              }       
    if(k==length(pat)+1) break
  }
  return(  all(lv)   )
}

Are there any more efficient solutions, this function is too slow for me

3 Answers

We could paste them and use either grepl

grepl(paste(pat, collapse=".*"), paste(dat, collapse=""))
#[1] TRUE

or str_detect

library(stringr)
str_detect(paste(dat, collapse=""), paste(pat, collapse=".*"))
#[1] TRUE

Another option:

yes.seq <- function(pat, dat) {
  all(pat %in% dat) && all(diff(na.omit(match(pat, dat))) > 0)
}
yes.seq(pat, dat)
# [1] TRUE
yes.seq(c(pat, "ZZ"), dat)
# [1] FALSE
yes.seq(pat, rev(dat))
# [1] FALSE

Here is another base R option

yes.seq <- function(pat,dat) identical(order(match(pat, dat)), seq_along(pat))
Related