我有一个向量。
data <- c("ta", "tb", "tc", "tk", "tf")
我如何将这个向量转化为一个列表,其中包含n个(其中n的范围为2到length(data)-1)相邻元素的每个可能组合?列表应该如下所示(每行代表一个列表元素)。
"ta", "tb"
"tb", "tc"
"tc", "tk"
"tk", "tf"
"ta", "tb", "tc"
"tb", "tc", "tk"
"tc", "tk", "tf"
"ta", "tb", "tc", "tk"
"tb", "tc", "tk", "tf"
我需要执行这个操作很多次,所以速度很重要。谢谢!我有一个向量:data(数据)。
myFun <- function(Data) {
A <- lapply(2:(length(Data)-1L), sequence)
B <- lapply(rev(lengths(A))-1L, function(x) c(0, sequence(x)))
unlist(lapply(seq_along(A), function(x) {
lapply(B[[x]], function(y) Data[A[[x]]+y])
}), recursive = FALSE, use.names = FALSE)
}
使用方法
myFun(data)
以下是使用以下方法的解决方案 rollapply
从 "动物园"。
myFun <- function(Data, singles = FALSE) {
require(zoo)
x <- 2:(length(Data)-1)
out <- lapply(x, function(y) rollapply(Data, FUN = c, width = y))
if (isTRUE(singles)) {
out <- unlist(lapply(out, function(y) split(y, sequence(nrow(y)))),
recursive = FALSE, use.names = FALSE)
}
out
}
如果你想把上面的输出按行分开(每个项目都是一个新的列表项目),使用 singles = TRUE
参数。
myFun(data, singles = TRUE)
# [[1]]
# [1] "ta" "tb"
#
# [[2]]
# [1] "tb" "tc"
#
#######
# SNIP
#######
#
# [[8]]
# [1] "ta" "tb" "tc" "tk"
#
# [[9]]
# [1] "tb" "tc" "tk" "tf"
这里有一个方法,使用 data.table
's vecseq
功能。基本上。vecseq(x, y, clamp)
对于x中的每一个数字,从相应的索引中获取y的值,并构造序列x:(x+len)。即: vecseq(c(1L, 4L), c(2L, 6L), 5L)
构建序列 c(1L, 2L, 4L, 5L, 6L)
. 该 clamp
论点只是一个论点,它 应 要>=答案的长度。如果你不知道,可以直接给出一个比较大的数字。
我们的想法是使用 vecseq
然后进行拆分,得到相应的列表。我希望通过一步步运行下面的代码,事情应该是显而易见的(只要花点小力气:)。
data <- c("ta", "tb", "tc", "tk", "tf")
require(data.table)
ff <- data.table:::vecseq
my_fun <- function(data) {
xmin = 2L
xmax = length(data)-1L
len = xmax-xmin+1L
tot = sum(xmax:xmin)
t1 = ff(rep(1L, len), xmax:xmin, tot)
t2 = rep.int(xmin:xmax, xmax:xmin)
idx = ff(t1,t2,sum(t2))
dt = data.table(x=data[idx], id=rep.int(seq_along(t2), t2))
setattr(dt, 'sorted', 'id')
dt[J(seq_along(t2)), list(list(x))]$V1
}
这看起来相当快,与@flodel的(优秀)答案是一致的。当数据的长度达到250左右时,两者相差0.2秒左右(这个解决方案更快)。所以,差别不大。
这里有一个方法。
adj.poss <- function(x) {
n <- length(x)
stopifnot(n > 2L)
idx <- expand.grid(start = 1L:n, len = 2L:(n-1L))
idx$end <- idx$start + idx$len - 1L
idx <- idx[idx$end <= n, ]
Map(function(start, end) x[start:end], idx$start, idx$end)
}
这里有一个方法: adj.poss(data)
给出您的预期输出,顺序与您指定的完全相同。