Вот некоторые тесты различных подходов, предложенных до сих пор для 1000 строк длиной 1000. Вариант подхода Акруна, который опирается на charToRaw()
вместо strsplit()
, кажется самым быстрым.
Unit: milliseconds
expr min lq mean median uq max neval cld
strsplit 38.626212 38.868298 42.48461 42.43953 45.87118 46.32892 10 a
distance 6437.995304 6783.890225 6968.59793 7016.14651 7184.29213 7319.84097 10 b
bitwXor 12.065822 12.278691 17.32897 18.52006 19.95079 26.90822 10 a
toRaw 4.572742 4.693785 7.76573 4.87048 10.73064 18.74406 10 a
Код для воспроизведения:
set.seed(5)
size <- 1000
cvec <- replicate(size, paste0(sample(letters, size, replace = TRUE), collapse = ""))
cvec2 <- sapply(cvec, function(x) `substring<-`(x, {y <- sample(size, 1)}, y, sample(letters, 1)))
microbenchmark::microbenchmark(
strsplit = mapply(function(x, y) which(x != y)[1],
strsplit(cvec, ""), strsplit(cvec2, "")),
distance = {res <- mapply(function(x, y)
grepRaw(diag(attr(adist(x, y, counts = TRUE), "trafos")), pattern = "S|D|I"),
cvec,
cvec2, USE.NAMES = FALSE)
res[lengths(res) == 0] <- NA
unlist(res)},
bitwXor = {res <- mapply(function(x,y) which(bitwXor(utf8ToInt(x),utf8ToInt(y))>0), cvec,cvec2, USE.NAMES = FALSE)
res[lengths(res) == 0] <- NA
unlist(res)},
toRaw = mapply(function(x, y) which(charToRaw(x) != charToRaw(y))[1],
cvec, cvec2, USE.NAMES = FALSE),
times = 10, check = "equal")