How can to generate all possible consecutive n-tuples of a vector in R ?
# Input
x <- c('a', 'b', 'c', 'b')
n = 2
# Output
list(c('a', 'b'), c('b', 'c'), c('c', 'b')) # a list equal to this list
CodePudding user response:
We may remove the first and last elements and concatenate by looping over the corresponding elements with Map
Map(c, x[-length(x)], x[-1])
$a
[1] "a" "b"
$b
[1] "b" "c"
$c
[1] "c" "b"
Or cbind
to a matrix
and split by row with asplit
asplit(cbind(x[-length(x)], x[-1]), 1)
[[1]]
[1] "a" "b"
[[2]]
[1] "b" "c"
[[3]]
[1] "c" "b"
If the n
values can be more than 2, we may also do this with shift
library(data.table)
Filter(\(x) all(complete.cases(x)),
data.table::transpose(shift(x, seq_len(n)-1, type = 'lead')))
[[1]]
[1] "a" "b"
[[2]]
[1] "b" "c"
[[3]]
[1] "c" "b"
CodePudding user response:
I prefer to using a matrix to store the results:
n <- 2
mat2 <- matrix(x[sequence(rep(length(x) - n 1, n), 1:n)], ncol = n)
# [,1] [,2]
#[1,] "a" "b"
#[2,] "b" "c"
#[3,] "c" "b"
n <- 3
mat3 <- matrix(x[sequence(rep(length(x) - n 1, n), 1:n)], ncol = n)
# [,1] [,2] [,3]
#[1,] "a" "b" "c"
#[2,] "b" "c" "b"
If you insist on using a list, then:
n <- 2
lst2 <- split(x[sequence(rep(length(x) - n 1, n), 1:n)], seq_len(length(x) - n 1))
#$`1`
#[1] "a" "b"
#
#$`2`
#[1] "b" "c"
#
#$`3`
#[1] "c" "b"
n <- 3
lst3 <- split(x[sequence(rep(length(x) - n 1, n), 1:n)], seq_len(length(x) - n 1))
#$`1`
#[1] "a" "b" "c"
#
#$`2`
#[1] "b" "c" "b"
I don't use embed
or asplit
. They have a for
-loop inside.