Эффективно заменить строки в 20 000 потенциальных совпадений - PullRequest
0 голосов
/ 18 октября 2019

Я хочу заменить подстроки строки и хочу проверить на 20k + кандидатов.

Есть ли более эффективный способ, чем разделить 20k на подгруппы из 900 кандидатов и зациклить их? Могу ли я сделать этот поиск в <0,3 с? </p>

Что я пробовал:

1) Вставить 20 тыс. Кандидатов в строку. Это приводит к ошибке, см. Ниже. (Возможно, слишком длинная строка для 64-битной версии?)

2) Создайте подгруппы из 900 кандидатов и выполните цикл по подгруппам. (Это занимает больше секунды).

Воспроизводимый код:

n <- 20000 # have to go down to 900 here. 
words <- sapply(sample(4:10, size = n, replace = T), FUN = function(nr){
  paste(sample(letters, nr, replace = T), collapse = "")
})


sentence <- "This is my sentence where i want to replace matches"
replacement <- "REPLACEMENT"

library(microbenchmark)
pattern <- paste(words, collapse = "|") # probably too long for a string
clean <- gsub(pattern = pattern, replacement = replacement, x = sentence) # fails

Ответы [ 2 ]

3 голосов
/ 18 октября 2019

Я предлагаю использовать регулярное выражение для сопоставления любых символов слова (\w+) и обратный вызов в качестве аргумента замены для stringr::str_replace_all:

str_replace_all(sentence, "\\w+", function(w) ifelse(w %in% words, replacement, w))

Тест:

> microbenchmark::microbenchmark(splitmatch = { str_replace_all(sentence, "\\w+", function(w) ifelse(w %in% words, replacement, w)) })
Unit: milliseconds
       expr      min      lq     mean   median       uq      max neval
 splitmatch 1.217353 1.26916 1.545855 1.395634 1.678778 4.982447   100
1 голос
/ 18 октября 2019

Разделите предложение на слова:

n <- 20000 # have to go down to 900 here. 
words <- sapply(sample(4:10, size = n, replace = T), FUN = function(nr){
  paste(sample(letters, nr, replace = T), collapse = "")
})

words[1e4] <- "i" #to have a match

sentence <- "This is my sentence where i want to replace matches"
replacement <- "REPLACEMENT"

microbenchmark::microbenchmark(splitmatch =
  {
    splitsentence <- strsplit(sentence, " ")[[1]]

    matches <- vapply(splitsentence, function(x) x %in% words, FUN.VALUE = TRUE)

    splitsentence[matches] <- replacement

    paste(splitsentence, collapse = " ")
    #[1] "This is my sentence where REPLACEMENT want to replace matches"
  })
#Unit: microseconds
#      expr   min     lq     mean median      uq    max neval
#splitmatch 957.4 986.95 1222.963 995.15 1005.85 7534.6   100
...