生成R中列表的所有不同排列

tre*_*bot 51 r permutation

我正在尝试创建列表的排列列表,例如perms(list("a", "b", "c"))返回

list(list("a", "b", "c"), list("a", "c", "b"), list("b", "a", "c"),
     list("b", "c", "a"), list("c", "a", "b"), list("c", "b", "a"))
Run Code Online (Sandbox Code Playgroud)

我不知道如何继续,任何帮助将不胜感激.

koh*_*ske 52

combinat::permn 会做那件事:

> library(combinat)
> permn(letters[1:3])
[[1]]
[1] "a" "b" "c"

[[2]]
[1] "a" "c" "b"

[[3]]
[1] "c" "a" "b"

[[4]]
[1] "c" "b" "a"

[[5]]
[1] "b" "c" "a"

[[6]]
[1] "b" "a" "c"
Run Code Online (Sandbox Code Playgroud)

请注意,如果元素很大,计算量很大.


Mus*_*ful 44

前一阵子我不得不在基地R做这个,而不加载任何包.

permutations <- function(n){
    if(n==1){
        return(matrix(1))
    } else {
        sp <- permutations(n-1)
        p <- nrow(sp)
        A <- matrix(nrow=n*p,ncol=n)
        for(i in 1:n){
            A[(i-1)*p+1:p,] <- cbind(i,sp+(sp>=i))
        }
        return(A)
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

> matrix(letters[permutations(3)],ncol=3)
     [,1] [,2] [,3]
[1,] "a"  "b"  "c" 
[2,] "a"  "c"  "b" 
[3,] "b"  "a"  "c" 
[4,] "b"  "c"  "a" 
[5,] "c"  "a"  "b" 
[6,] "c"  "b"  "a" 
Run Code Online (Sandbox Code Playgroud)

  • 功能不错.看起来也很快. (2认同)

A5C*_*2T1 33

您可以permutations()gtools包中尝试,但与之不同的permn()combinat,它不会输出列表:

> library(gtools)
> permutations(3, 3, letters[1:3])
     [,1] [,2] [,3]
[1,] "a"  "b"  "c" 
[2,] "a"  "c"  "b" 
[3,] "b"  "a"  "c" 
[4,] "b"  "c"  "a" 
[5,] "c"  "a"  "b" 
[6,] "c"  "b"  "a" 
Run Code Online (Sandbox Code Playgroud)

  • 值得注意的是,"排列"更灵活.它允许排列m个n个元素并允许重复使用元素.我在尝试'permn`后没有成功就找到了这个. (5认同)

小智 29

基地R也可以提供答案:

all <- expand.grid(p1 = letters[1:3], p2 = letters[1:3], p3 = letters[1:3], stringsAsFactors = FALSE) 
perms <- all[apply(all, 1, function(x) {length(unique(x)) == 3}),]
Run Code Online (Sandbox Code Playgroud)


Adr*_*ian 10

基本R中的解决方案,不依赖于其他包:

> getPerms <- function(x) {
    if (length(x) == 1) {
        return(x)
    }
    else {
        res <- matrix(nrow = 0, ncol = length(x))
        for (i in seq_along(x)) {
            res <- rbind(res, cbind(x[i], Recall(x[-i])))
        }
        return(res)
    }
}

> getPerms(letters[1:3])
     [,1] [,2] [,3]
[1,] "a"  "b"  "c" 
[2,] "a"  "c"  "b" 
[3,] "b"  "a"  "c" 
[4,] "b"  "c"  "a" 
[5,] "c"  "a"  "b" 
[6,] "c"  "b"  "a"
Run Code Online (Sandbox Code Playgroud)

我希望这有帮助.

  • 优于“gtools”解决方案。 (3认同)

rns*_*nso 9

尝试:

> a = letters[1:3]
> eg = expand.grid(a,a,a)
> eg[!(eg$Var1==eg$Var2 | eg$Var2==eg$Var3 | eg$Var1==eg$Var3),]
   Var1 Var2 Var3
6     c    b    a
8     b    c    a
12    c    a    b
16    a    c    b
20    b    a    c
22    a    b    c
Run Code Online (Sandbox Code Playgroud)

正如@Adrian在评论中所建议的那样,最后一行可以替换为:

eg[apply(eg, 1, anyDuplicated) == 0, ]
Run Code Online (Sandbox Code Playgroud)


Ric*_*ick 9

# Another recursive implementation    
# for those who like to roll their own, no package required 
    permutations <- function( x, prefix = c() )
    {
        if(length(x) == 0 ) return(prefix)
        do.call(rbind, sapply(1:length(x), FUN = function(idx) permutations( x[-idx], c( prefix, x[idx])), simplify = FALSE))
    }

    permutations(letters[1:3])
    #    [,1] [,2] [,3]
    #[1,] "a"  "b"  "c" 
    #[2,] "a"  "c"  "b" 
    #[3,] "b"  "a"  "c" 
    #[4,] "b"  "c"  "a" 
    #[5,] "c"  "a"  "b" 
    #[6,] "c"  "b"  "a" 
Run Code Online (Sandbox Code Playgroud)

  • 很好的答案!删除 `sapply(..., simple = FALSE)` 并使用 `lapply(...)` 怎么样? (2认同)

Arn*_*d A 5

一个有趣的解决方案“概率”,使用样本作为基数R:

elements <- c("a", "b", "c")
k <- length(elements)
res=unique(t(sapply(1:200, function(x) sample(elements, k))))
# below, check you have all the permutations you need (if not, try again)
nrow(res) == factorial(k)
res
Run Code Online (Sandbox Code Playgroud)

基本上,您调用了许多随机样本,希望将它们全部收集起来,然后对它们进行唯一化。