找到所有相邻的组合

问题描述 投票:4回答:3

我有一个向量。

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(数据)。

r vector combinations elements
3个回答
2
投票

编辑:新功能

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"

2
投票

这里有一个方法,使用 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秒左右(这个解决方案更快)。所以,差别不大。


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

© www.soinside.com 2019 - 2024. All rights reserved.