查找所有相邻组合

时间:2013-11-23 00:43:01

标签: r vector combinations elements

我有一个矢量:

data <- c("ta", "tb", "tc", "tk", "tf")

如何将此向量转换为一个列表,其中包含n个(其中n的范围从2到长度(数据)-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"

我需要多次执行此操作,因此速度很重要。谢谢!

3 个答案:

答案 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)给出您的预期输出,其顺序与您指定的完全相同。

答案 1 :(得分:2)

以下是使用data.table的{​​{1}}函数的方法。基本上,vecseq取x中的每个数字,来自相应索引的y值,并构造序列x:(x + len)。也就是说,vecseq(x, y, clamp)构造序列vecseq(c(1L, 4L), c(2L, 6L), 5L)c(1L, 2L, 4L, 5L, 6L)参数只是 应该<=> =答案长度的参数。如果你不知道,你可以给出一个相对较大的数字。

我们的想法是使用clamp生成索引,然后拆分以相应地获取列表。我希望通过逐步运行下面的代码,事情应该是显而易见的(稍加努力:))。

vecseq

这看起来非常快,与@ flodel的(优秀)答案相同。当数据长度达到250左右时,差异大约为0.2秒(此解决方案更快)。所以,没有太大区别。

答案 2 :(得分:2)

编辑:新功能

myFun <- function(Data) {
  A <- lapply(2:(length(Data)-1), sequence)
  B <- lapply(rev(vapply(A, length, 1L))-1, 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)

原始功能

以下是使用“zoo”中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"
相关问题