如何创建子集的组合,以使最终集不包含重复元素

时间:2019-05-11 23:21:13

标签: r vectorization combinations combn

我正在尝试创建列表的子集,以最终输出与初始列表长度相同且没有重复元素的条件覆盖所有可能的组合。

对于列表:

X <- c("A","B","C","D")

所有非空子集都是(我们称之为Y):

[('A'), ('B'), ('C'), ('D'), ('A', 'B'), ('A', 'C'), ('A', 'D'), ('B', 'C'),
('B', 'D'), ('C', 'D'), ('A', 'B', 'C'), ('A', 'B', 'D'), ('A', 'C', 'D'), 
('B', 'C', 'D'), ('A', 'B', 'C', 'D')]

我要寻找的是Y的组合,这样组合中的元素就是X的不同值。

一些可以接受的组合是:

 (('A',), ('B',), ('C', 'D'))
 (('A',), ('C',), ('B', 'D'))
 (('A',), ('D',), ('B', 'C'))
 (('B',), ('C',), ('A', 'D'))
 (('B',), ('D',), ('A', 'C'))
 (('C',), ('D',), ('A', 'B'))

我尝试估算Y的所有可能组合,然后获取每种组合的不同值的长度。

如果length(distinct elements of combination) = length(X),则保留组合。但这无论如何都不是一种最佳方法,也不涵盖重复的场景。

在现实生活中,X中最多包含40个不同的元素。

2 个答案:

答案 0 :(得分:0)

这不是一个有效的解决方案,但可能会给其他人一些想法并吸引他们注意您的问题;

library(tidyverse)

do.call(c, lapply(seq_along(X), combn, x = X, simplify = FALSE)) %>% 
 map_chr(~ str_c(., collapse = ",")) %>% 
{do.call(c, lapply(seq_along(.), combn, x = ., simplify = FALSE))} %>%
 map_chr(~ str_c(., collapse = " ; ")) %>% as.data.frame() %>%  
  mutate(len = lengths(regmatches(., gregexpr(",|;", .))) + 1) %>% 
   setNames(., c("vec", "len")) %>% 
 bind_cols(., unqlen = unlist(lapply(.$vec, function(x)
                                     sum(!!str_count(as.character(x), LETTERS))))) %>%
 filter(unqlen == len & len == length(X)) %>% select(vec)

NB , 意味着在同一子集中和 ; 表示另一个子集;例如,A ; B,C,D等同于您的{A} , {B,C,D}

    #>              vec
    #> 1        A,B,C,D
    #> 2      A ; B,C,D
    #> 3      B ; A,C,D
    #> 4      C ; A,B,D
    #> 5      D ; A,B,C
    #> 6      A,B ; C,D
    #> 7      A,C ; B,D
    #> 8      A,D ; B,C
    #> 9    A ; B ; C,D
    #> 10   A ; C ; B,D
    #> 11   A ; D ; B,C
    #> 12   B ; C ; A,D
    #> 13   B ; D ; A,C
    #> 14   C ; D ; A,B
    #> 15 A ; B ; C ; D

reprex package(v0.2.1)于2019-05-13创建

答案 1 :(得分:-1)

X = c("A","B","C","D")

1:使用combn()

comb = c()
for(n in 1:length(X)){
  comb = c(comb, apply(combn(X, n), MARGIN = 2, FUN = "paste", collapse = ""))
}
comb
 [1] "A"    "B"    "C"    "D"    "AB"   "AC"   "AD"   "BC"   "BD"   "CD"   "ABC"  "ABD"  "ACD" 
[14] "BCD"  "ABCD"

2:使用expand.grid()

expand.grid(X, X)
   Var1 Var2
1     A    A
2     B    A
3     C    A
4     D    A
5     A    B
6     B    B
7     C    B
8     D    B
9     A    C
10    B    C
11    C    C
12    D    C
13    A    D
14    B    D
15    C    D
16    D    D