Test if a sentence is in another sentence

Viewed 48

I'm trying to determine if a string is a subset of another string. A possible solution is given by grepl function. For example

X<-"hello"
Y<-"hel"
grepl(Y, X, fixed = TRUE)

returns TRUE. I would like to obtain a similar result also for sentences and not only for single words. In this case:

grepl("John Tolkien", "John Ronald Reuel Tolkien", fixed = TRUE)
grepl("Tolkien John", "John Ronald Reuel Tolkien", fixed = TRUE)
grepl("John Ronald Tolkien", "John Ronald Reuel Tolkien", fixed = TRUE)

return FALSE, but I would like to obtain TRUE because John Tolkien, Tolkien John and John Ronald Tolkien are subsets of John Ronald Reuel Tolkien

1 Answers

You may use

regex.escape <- function(string) {
  gsub("([][{}()+*^$|\\\\?.])", "\\\\\\1", string)
}
BuildRegex <- function(search) {
    x<-strsplit(search,"\\s+")
    paste0("^(?=.*(?<!\\w)", paste(regex.escape(unlist(x)), collapse="(?!\\w))(?=.*(?<!\\w)"), "(?!\\w))")
}
grepl(BuildRegex("John Tolkien"), "John Ronald Reuel Tolkien", perl=TRUE)
## => TRUE
grepl(BuildRegex("Tolkien John"), "John Ronald Reuel Tolkien", perl=TRUE)
## => TRUE
grepl(BuildRegex("John Ronald Tolkien"), "John Ronald Reuel Tolkien", perl=TRUE)
## => TRUE

See the R demo.

The resulting regex is ^(?=.*(?<!\w)John(?!\w))(?=.*(?<!\w)Tolkien(?!\w)):

  • ^ - start of string location
  • (?=.*(?<!\w)John(?!\w)) - John as a whole word after any zero or more chars other than line break chars as many as possible
  • (?=.*(?<!\w)Tolkien(?!\w)) - Tolkien as a whole word after any zero or more chars other than line break chars as many as possible.

If there are more than three words, there will be three lookaheads in the resulting regex.

Related