1

I'm trying to split-up a vector to get all possible combinations of sub-sequences of numerically-contiguous elements.

Each permutation of the split needs to include all elements of the vector, and the relevant sequences will be those that fall in ascending order.

Here is an example of what I'm trying to describe:

# sample vector
x <- 1:3

# desired output
sets <- list(s1 = list(1, 2, 3), # x split into 3 vectors
             s2 = list(1, 2:3),  # x split into two vectors 1 vs 2:3
             s3 = list(1:2, 3))  # x split into two vectors 1:2 vs 3

Coding this by hand works, but gets tedious when using longer vectors.

I am aware that there are ways to get all possible sub-sequences of a vector but I am having trouble seeing how I might split-up a vector to achieve these sets of subsequences. Any ideas?

Edit To explain with greater precision, my example shows the output as having sets of different combinations list(s1, s2, s3). So the ideal output is a list-of-lists, and not just a single flat list of the possible combinations.

xilliam
  • 2,074
  • 2
  • 15
  • 27
  • 1
    I think you need to look at [vector partitions](https://stackoverflow.com/questions/10661105/how-can-i-get-a-list-of-all-possible-partitions-of-a-vector-in-r) – Eric Dec 20 '21 at 11:04
  • What happens in the case of `x <- 1:4`? E.g. `(1:2, 3:4), (1:3, 4), ...` are also allowed? – Christoph Dec 20 '21 at 11:05
  • @Christoph I believe the answer to your question is yes. Here is my attempt to give a complete list for 1:4. ```list(s1 = list(1, 2, 3, 4), s2 = list(1, 2:4), s3 = list(1, 2, 3:4), s4 = list(1, 2:3, 4), s5 = list(1:2, 3:4), s6 = list(1:3, 4))``` – xilliam Dec 20 '21 at 11:10

2 Answers2

1

You can try the code below using split + findInterval + combn

v <- seq_along(x)
Map(
  split,
  list(x),
  unique(
    lapply(
      unlist(
        sapply(
          seq_along(v),
          function(k) combn(v, k, simplify = FALSE)
        ),
        recursive = FALSE
      ),
      function(p) {
        cumsum(duplicated(findInterval(v, p)))
      }
    )
  )
)

Some example results

  • For x <- 1:3, we obtain
[[1]]
[[1]]$`0`
[1] 1

[[1]]$`1`
[1] 2

[[1]]$`2`
[1] 3


[[2]]
[[2]]$`0`
[1] 1 2

[[2]]$`1`
[1] 3


[[3]]
[[3]]$`0`
[1] 1

[[3]]$`1`
[1] 2 3


[[4]]
[[4]]$`0`
[1] 1 2 3
  • For x <- 1:4, we obtain
[[1]]
[[1]]$`0`
[1] 1

[[1]]$`1`
[1] 2

[[1]]$`2`
[1] 3

[[1]]$`3`
[1] 4


[[2]]
[[2]]$`0`
[1] 1 2

[[2]]$`1`
[1] 3

[[2]]$`2`
[1] 4


[[3]]
[[3]]$`0`
[1] 1

[[3]]$`1`
[1] 2 3

[[3]]$`2`
[1] 4


[[4]]
[[4]]$`0`
[1] 1

[[4]]$`1`
[1] 2

[[4]]$`2`
[1] 3 4


[[5]]
[[5]]$`0`
[1] 1 2 3

[[5]]$`1`
[1] 4


[[6]]
[[6]]$`0`
[1] 1 2

[[6]]$`1`
[1] 3 4


[[7]]
[[7]]$`0`
[1] 1

[[7]]$`1`
[1] 2 3 4


[[8]]
[[8]]$`0`
[1] 1 2 3 4
ThomasIsCoding
  • 96,636
  • 9
  • 24
  • 81
0

I think that this will do the trick:

> x <- 1:4
> unlist(sapply(1:length(x), function(i) 
   combn(x, i, function(y) 
     as.list(as.data.frame(y)) )), recursive = F)
[[1]]
[1] 1

[[2]]
[1] 2

[[3]]
[1] 3

[[4]]
[1] 4

[[5]]
[1] 1 2

[[6]]
[1] 1 3

[[7]]
[1] 1 4

[[8]]
[1] 2 3

[[9]]
[1] 2 4

[[10]]
[1] 3 4

[[11]]
[1] 1 2 3

[[12]]
[1] 1 2 4

[[13]]
[1] 1 3 4

[[14]]
[1] 2 3 4

[[15]]
[1] 1 2 3 4
Tur
  • 604
  • 4
  • 9
  • Thanks. This gives the combinations of elements, but I loses the information about each 'set'. The ideal output provides a list of lists as the output, and with each list element being a list of a single set. This answer is a flat list. Also, each set needs 'contiguous' elements. So something with 3 vs 1,2,4 is would not be included. But 1 vs 2,3,4 would be included. – xilliam Dec 20 '21 at 12:23