Reputation: 23
I have a vector of K elements and I need to check if it contains a precise subset of 2 consecutive elements.
Assume K = 6
vec = c(4,4,3,1,2,2)
How can I get an indicator that checks for the subset (4,2) as consecutive elements? Should return FALSE in this example while (3,1) should return TRUE.
Upvotes: 2
Views: 364
Reputation: 5456
Especially if you have more than 2 elements to check, this might be worthwhile:
vec <-= c(4,4,3,1,2,2)
chk <- c(3, 1)
as.logical(length(Reduce(intersect, lapply(seq_along(chk), function(x) which(chk[x] == lead(vec, x - 1))))))
# [1] TRUE
chk <- c(4, 1)
as.logical(length(Reduce(intersect, lapply(seq_along(chk), function(x) which(chk[x] == lead(vec, x - 1))))))
# [1] FALSE
Upvotes: 1
Reputation: 269644
1) Use rollapply with the identical function.
library(zoo)
vec <- c(4,4,3,1,2,2)
x <- c(4, 2)
any(rollapply(vec, length(x), identical, x))
## [1] FALSE
x <- c(3, 1)
any(rollapply(vec, length(x), identical, x))
## [1] TRUE
2) Create strings out of vec and x and use grepl:
x <- c(4, 2)
grepl(sprintf("\\b%s\\b", toString(x)), toString(vec))
## [1] FALSE
x <- c(3, 1)
grepl(sprintf("\\b%s\\b", toString(x)), toString(vec))
## [1] TRUE
3) If x always has two elements then:
x <- c(4, 2)
any(head(vec, -1) == x[1] & tail(vec, -1) == x[2])
## [1] FALSE
x <- c(3, 1)
any(head(vec, -1) == x[1] & tail(vec, -1) == x[2])
## [1] TRUE
Upvotes: 2
Reputation: 39858
One another approach could be:
grepl("42", paste(vec, collapse = ""))
[1] FALSE
grepl("31", paste(vec, collapse = ""))
[1] TRUE
Upvotes: 3
Reputation: 545598
Using base R:
find_subsequence = function (vec, needle) {
sub_idx = seq_along(needle) - 1L
Filter(
function (i) all(needle == vec[sub_idx + i]),
seq_len(length(vec) - length(needle) + 1L)
)
}
find_subsequence(vec, c(3, 1))
# [1] 4
find_subsequence(vec, c(4, 2))
# integer(0)
Upvotes: 1