R:限制置换比使用for循环更有效

R:限制置换比使用for循环更有效,r,for-loop,recursion,R,For Loop,Recursion,我试图排列一个可变长度的字符向量a,每次选取3个元素,不重复。排序仅对第一个元素有效,但对第二个和第三个元素无效(例如abc!=bac!=cab,但abc=acb和bca=bac)。每组3个排列元素应该是数据帧b中的一行 带有字母A、b、c、d、e的向量将产生该预期输出: abc abd abe acd ace ade bac bad bae bcd bce bde cab cad cae cbd cbe cde dab dac dae dbc dbe dce eab eac ead

我试图排列一个可变长度的字符向量
a
,每次选取3个元素,不重复。排序仅对第一个元素有效,但对第二个和第三个元素无效(例如abc!=bac!=cab,但abc=acb和bca=bac)。每组3个排列元素应该是数据帧
b
中的一行

带有字母A、b、c、d、e的向量将产生该预期输出:

abc
abd
abe
acd
ace
ade

bac
bad
bae
bcd
bce
bde

cab 
cad
cae
cbd
cbe
cde

dab
dac
dae
dbc
dbe
dce

eab
eac
ead
ebc
ebd
ecd
使用3 for循环,我想我能够实现这个输出,但是如果向量很长,速度会很慢

a=字母[1:5]
aL=长度(a)
b.a.i.a.j.a.k。
#>1 a b c
#>2 a b d
#>3 a b e
#>4 a c d
#>5 a c e
#>6 a d e
#>7 b a c
#>8 b a d
#>9 b a e
#>10 b c d
#>11 b c e
#>12 b d e
#>13 c a b
#>14 c a d
#>15 c a e
#>16 c b d
#>17 c b e
#>18 c d e
#>19 d a b
#>20天
#>21 d a e
#>22 d b c
#>23 d b e
#>24 d c e
#>25 e a b
#>26 e a c
#>27 e a d
#>28 e b c
#>29 e b d
#>30东、中、西
由(v0.2.1)于2019-07-2017年创建

如何在更短的时间内达到相同的结果。递归更快吗


非常感谢您的帮助。谢谢。

对于您的具体示例,这里有一个选项:

library(gtools)
library(dplyr)

# example vector
vec = letters[1:5]

# vectorised function to rearrange elements (based on your restriction)
f = function(x1,x2,x3) paste0(c(x1, sort(c(x2,x3))), collapse = " ")
f = Vectorize(f)

permutations(length(vec), 3, vec) %>%      # get permutations
  data.frame(., stringsAsFactors = F) %>%  # save as data frame
  mutate(vec = f(X1,X2,X3)) %>%            # apply function to each row
  distinct(vec, .keep_all = T)             # keep distinct vec values

#    X1 X2 X3   vec
# 1   a  b  c a b c
# 2   a  b  d a b d
# 3   a  b  e a b e
# 4   a  c  d a c d
# 5   a  c  e a c e
# 6   a  d  e a d e
# 7   b  a  c b a c
# ...

不清楚是希望输出为3个单独的列,每个列包含1个元素,还是一个列包含向量,所以我保留这两个列供您选择。您可以保留列
{X1、X2、X3}
或只保留
vec

我建议以下解决方案:

a = letters[1:5]
A = t(combn(a,3)) # create all possible three-letter combinations, 
                  # disregarding the order 
Full = rbind(A, A[,3:1], A[,c(2,3,1)]) # put every of the elements of the 
                                       # differing combinations in first place once

以下是将triple
for
循环直接重写为triple
lappy
循环

t1 <- system.time({
for(i in 1:aL){
  for(j in 1:(aL-1)){
    for(k in (j+1):aL){
      if(j != i & k != i) { 
        b <- rbind(b, data.frame(a[i], a[j], a[k])) }
    }
  }
}
})

t2 <- system.time({
d <- lapply(1:aL, function(i){
  tmp <- lapply(1:(aL-1), function(j){
    tmp <- lapply((j+1):aL, function(k){
      if(j != i & k != i) c(a[i], a[j], a[k])
    })
    do.call(rbind, tmp)
  })
  do.call(rbind, tmp)
})
d <- do.call(rbind.data.frame, d)
names(d) <- paste("a", 1:3, sep = ".")
})

all.equal(b, d)
#[1] "Names: 3 string mismatches"

rbind(t1, t2)
#   user.self sys.self elapsed user.child sys.child
#t1     0.051        0   0.051          0         0
#t2     0.017        0   0.018          0         0

t1他似乎不想要“aab”或“bbb”类型的复制品。他的示例中的所有元素都由三个不同的字母组成,因此“expand.grid(a,a,a)”不起作用。您必须找到一种方法来省略这些不需要的行