简体   繁体   English

在R中查找具有约束的值的组合

[英]Finding combinations of values with constraints in R

I have a set of values in a vector, eg 我在向量中有一组值,例如

all_points <- c(1, 4, 2, 12, 6, 5, 25)

I want to find all possible combinations where the numbers from left to right are in ascending order. 我想找到所有可能的组合,其中数字从左到右按升序排列。 The first and last numbers will always be included. 第一个和最后一个数字将始终包含在内。 For example, in this case they would be: 例如,在这种情况下,它们将是:

1, 4, 12, 25
1, 4, 6, 25
1, 4, 25
1, 2, 12, 25
1, 2, 6, 25
1, 2, 5, 25
1, 2, 25
1, 12, 25
1, 6, 25
1, 5, 25
1, 25

At the moment, I am trying to implement a recursive function that tests the size of all rightward values, and returns a list of vectors, but it isn't working. 目前,我正在尝试实现一个递归函数,该函数测试所有向右值的大小,并返回向量列表,但是它不起作用。 Included below is part R code and part pseudocode to explain my approach. 下面包括R部分代码和伪代码部分,以说明我的方法。

my_recursive_function <- function(input_points, running_vector = c(1)){
    start_point <- input_points[1]
    rightward_points <- input_points[2:length(input_points)
    for(i in 1:length(rightward_points)){
        if(rightward_points[i] != 25 & rightward_points[i] > start_point){
            set_of_points <- c(running_vector, rightward_points[i])
            my_recursive_function(rightward_points, set_of_points)
        }
        if(rightward_points[i] == 25){
            print(c(running_vector, 25)
            flush.console()
            #I will end up doing more than printing here, but this is enough for the example
        }

        #do something to return to the previous level of recursion, 
        #including returning running_vector and rightward_points
        #to the appropriate states
    }

So hopefully that kind of makes sense. 因此,希望这种说法有意义。 I have 2 questions: 我有两个问题:

  1. Am I overcomplicating this, and there is a better way? 我是否使这个问题复杂化了,还有更好的方法吗? This is kind of a search algorithm, traversing a tree structure, so there might be something smart I can do here that I can't see. 这是一种遍历树结构的搜索算法,因此在这里可能有些聪明的事情我看不到。
  2. If this is the best way, how do I do the pseudocode bit at the bottom? 如果这是最好的方法,我该如何做底部的伪代码位? I'm getting very confused trying to work out what each vector looks like, in each level of recursion, and how to pop elements off my running_vector. 我感到非常困惑,试图弄清楚每个向量的外观,每次递归级别以及如何从我的running_vector中弹出元素。

One possible approach is to use combn with different lengths to create all possible combinations as follows: 一种可能的方法是使用具有不同长度的combn来创建所有可能的组合,如下所示:

combis <- lapply(0L:(length(all_points)-2L), 
            function(n) combn(
                seq_along(all_points)[c(-1L, -length(all_points))], 
                n, 
                function(x) all_points[x],
                FALSE))

lapply(unlist(combis, recursive=FALSE),
    function(x) c(all_points[1L], x, all_points[length(all_points)]))

Explanation 说明

1) The first line of code takes the number of elements ( n ) between first and last element and generate all possible combinations of indices and then extracts the corresponding elements using function(x) all_points[x] 1)代码的第一行采用第一个元素与最后一个元素之间的元素数( n ),并生成所有可能的索引组合,然后使用function(x) all_points[x]提取相应的元素

2) unlist(..., recursive=FALSE) unnest the list by 1 level. 2) unlist(..., recursive=FALSE)将列表unlist(..., recursive=FALSE) 1级。

3) lapply(..., function(x) c(sorted[1L], x, sorted[length(sorted)])) appends the first and last element to each combination 3) lapply(..., function(x) c(sorted[1L], x, sorted[length(sorted)]))将第一个和最后一个元素附加到每个组合

Output 产量

[[1]]
[1]  1 25

[[2]]
[1]  1  4 25

[[3]]
[1]  1  2 25

[[4]]
[1]  1 12 25

[[5]]
[1]  1  6 25

[[6]]
[1]  1  5 25

[[7]]
[1]  1  4  2 25

[[8]]
[1]  1  4 12 25

[[9]]
[1]  1  4  6 25

[[10]]
[1]  1  4  5 25

[[11]]
[1]  1  2 12 25

[[12]]
[1]  1  2  6 25

[[13]]
[1]  1  2  5 25

[[14]]
[1]  1 12  6 25

[[15]]
[1]  1 12  5 25

[[16]]
[1]  1  6  5 25

[[17]]
[1]  1  4  2 12 25

[[18]]
[1]  1  4  2  6 25

[[19]]
[1]  1  4  2  5 25

[[20]]
[1]  1  4 12  6 25

[[21]]
[1]  1  4 12  5 25

[[22]]
[1]  1  4  6  5 25

[[23]]
[1]  1  2 12  6 25

[[24]]
[1]  1  2 12  5 25

[[25]]
[1]  1  2  6  5 25

[[26]]
[1]  1 12  6  5 25

[[27]]
[1]  1  4  2 12  6 25

[[28]]
[1]  1  4  2 12  5 25

[[29]]
[1]  1  4  2  6  5 25

[[30]]
[1]  1  4 12  6  5 25

[[31]]
[1]  1  2 12  6  5 25

[[32]]
[1]  1  4  2 12  6  5 25

Here is a non recursive function. 这是一个非递归函数。 The output is a list of matrices, each of them with columns corresponding to the required vectors. 输出是矩阵列表,每个矩阵都有对应于所需向量的列。

non_recursive_function <- function(X){
  N <- length(X)
  X2 <- X[-c(1, N)]
  res <- lapply(seq_along(X2), function(k) t(combn(X2, k)))
  inx <- lapply(res, function(x){
    apply(x, 1, function(y) all(diff(y) > 0))
  })
  res <- lapply(seq_along(res), function(i) res[[i]][inx[[i]], ])
  res <- res[sapply(res, length) > 0]
  res <- lapply(res, function(x) 
    apply(as.matrix(x), 1, function(y) c(X[1], y, X[N])))
  res
}

all_points <- c(1, 4, 2, 12, 6, 5, 25)
x <- non_recursive_function(all_points)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM